P2500题解
Digital_Sunrise · · 题解
题外话
暴力碾标算
思路 & Coding
其实这一题非常的简单
首先,使用结构体来存储边
struct node
{
int u;
int v;
int w;
}e[500010];
然后,用一个数组
接着,如果输入让我们改变某一个点
我们只需要将
如果他让我们求最小边权,我们就把
将所有符合条件的边的边权取一个
void query(int num_1,int num_2)
{
int minn = INT_MAX;
for(int i = 1;i <= tot;i++)
{
int u = e[i].u;
int v = e[i].v;
int w = e[i].w;
if(fa[u] == num_1 and fa[v] == num_2) minn = min(minn,w);
if(fa[v] == num_1 and fa[u] == num_2) minn = min(minn,w);
}
if(minn == INT_MAX) printf("No Found!\n");
else printf("%lld\n",minn);
}
于是,代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
register int s = 0,w = 1;
register char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-')w = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0',ch = getchar();
return s * w;
}
int tot;
int n,m,q;
int fa[500010];
struct node
{
int u;
int v;
int w;
}e[500010];
void query(int num_1,int num_2)
{
int minn = INT_MAX;
for(int i = 1;i <= tot;i++)
{
int u = e[i].u;
int v = e[i].v;
int w = e[i].w;
if(fa[u] == num_1 and fa[v] == num_2) minn = min(minn,w);
if(fa[v] == num_1 and fa[u] == num_2) minn = min(minn,w);
}
if(minn == INT_MAX) printf("No Found!\n");
else printf("%lld\n",minn);
}
signed main()
{
for(int i = 1;i <= 500005;i++) fa[i] = 1;
n = read();
m = read();
for(int i = 1;i <= m;i++)
{
int u,v,w;
u = read();
v = read();
w = read();
e[++tot].u = u;
e[tot].v = v;
e[tot].w = w;
}
q = read();
while(q--)
{
string s;
int k;
cin >> s;
if(s == "MoveA")
{
scanf("%lld",&k);
fa[k] = 1;
}
else if(s == "MoveB")
{
scanf("%lld",&k);
fa[k] = 2;
}
else if(s == "MoveC")
{
scanf("%lld",&k);
fa[k] = 3;
}
else if(s == "AskAA") query(1,1);
else if(s == "AskAB") query(1,2);
else if(s == "AskAC") query(1,3);
else if(s == "AskBB") query(2,2);
else if(s == "AskBC") query(2,3);
else if(s == "AskCC") query(3,3);
}
return 0;
}
接着,恭喜您,TLE了!
妙啊
这时候,我们要想着如何优化
首先看修改操作
但显然
那我们想一想在搜索边的时候如何缩小
题目要求的是:
询问两个端点分别属于
x 集合和y 集合的所有边中最小的权值是多少。
那么,我们就设想,如何使我们找到第一个符合要求的边就是最小的边
答案很显然:先把边排序一边
这样能极大程度缩小遍历的范围
So,AC Coding:
#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
register int s = 0,w = 1;
register char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-')w = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0',ch = getchar();
return s * w;
}
int n,m,q;
int fa[500010];
struct node
{
int u;
int v;
int w;
}e[500010];
bool cmp(node x,node y)
{
return x.w < y.w;
}
void query(int num_1,int num_2)
{
int minn = INT_MAX;
for(int i = 1;i <= m;i++)
{
int u = e[i].u;
int v = e[i].v;
int w = e[i].w;
if(fa[u] == num_1 and fa[v] == num_2)
{
minn = min(minn,w);
break;
}
if(fa[v] == num_1 and fa[u] == num_2)
{
minn = min(minn,w);
break;
}
}
if(minn == INT_MAX) printf("No Found!\n");
else printf("%lld\n",minn);
}
signed main()
{
for(int i = 1;i <= 500005;i++) fa[i] = 1;
n = read();
m = read();
for(int i = 1;i <= m;i++)
{
int u,v,w;
u = read();
v = read();
w = read();
e[i].u = u;
e[i].v = v;
e[i].w = w;
}
sort(e + 1,e + m + 1,cmp);
q = read();
while(q--)
{
string s;
int k;
cin >> s;
if(s == "MoveA") k = read(),fa[k] = 1;
else if(s == "MoveB") k = read(),fa[k] = 2;
else if(s == "MoveC") k = read(),fa[k] = 3;
else if(s == "AskAA") query(1,1);
else if(s == "AskAB") query(1,2);
else if(s == "AskAC") query(1,3);
else if(s == "AskBB") query(2,2);
else if(s == "AskBC") query(2,3);
else if(s == "AskCC") query(3,3);
}
return 0;
}