修改后100分
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<vector>
#include<string>
#include<limits.h>
#include<cmath>
#include<map>
#include<queue>
#include<set>
#define iter(i,start,end) for(int (i)=(start);(i)<(end);(i)++)
#define vi vector<int>
using namespace std;
struct edge
{
int from ,to ,wei;
edge(int a,int b,int c):from(a),to(b),wei(c){};
};
const int maxnode=100000;
const int maxedge=200000;
const int cmax = 1000000 + 1;
int n,m;
int par[maxnode];
vector<edge>edges;
bool cmp(edge a,edge b){return a.wei < b.wei;}
void init();
void addedge(int from ,int to ,int wei);
void solve();
int findp(int node);
bool dfs(int cur,int par);
int main()
{
// freopen("201703-4.txt","r",stdin);
while(scanf("%d %d",&n,&m)==2)
{
init();
solve();
}
return 0;
}
void solve()
{
// bool start=false,end=false;
for(int i=0;i<edges.size();i++)
{
edge temp=edges[i];
int v=temp.from,u=temp.to,wei=temp.wei;
int pv=findp(v),pu=findp(u);
if(pv!=pu)
{
par[pv]=pu;
// if(v==0 || u==0 ) start=true;
// if(v==n-1 || u==n-1 ) end=true;
// if(start && end )
if(findp(0) ==findp(n-1))
{
cout<<edges[i].wei<<endl;
break;
}
}
}
}
void init()
{
edges.clear();
int from,to,wei;
for(int i=0;i<m;i++)
{
scanf("%d %d %d",&from,&to,&wei);
edges.push_back(edge(from-1,to-1,wei));
}
sort(edges.begin(),edges.end(),cmp);
iter(i,0,n)
par[i]=i;
}
int findp(int node)
{
return par[node]==node?node:par[node]=findp(par[node]);
}
之前一直WA,是因为对Kruskal算法不够了解,导致之前solve函数写成这样:
void solve()
{
bool start=false,end=false;
for(int i=0;i<edges.size();i++)
{
edge temp=edges[i];
int v=temp.from,u=temp.to,wei=temp.wei;
int pv=findp(v),pu=findp(u);
if(pv!=pu)
{
par[pv]=pu;
if(v==0 || u==0 ) start=true;
if(v==n-1 || u==n-1 ) end=true;
if(start && end )
//if(findp(0) ==findp(n-1))
{
cout<<edges[i].wei<<endl;
break;
}
}
}
}
也就是说我给起点和终点做了一个记号,一旦他们两个点都被merge了,那么就说明我最小生成树既扩到了起点,也扩到了终点,也就是说我起点找到了到终点的一条路,此时我就可以break并输出当下的路径的长度,就是起点到终点路上最长的弧了。
看起来似乎很对。。。实际上有可能起点和终点分别被merge在两个不同的集合中,如果我们把整个生成树全部生成出来,那么这两个集合最终一定会merge到一起,但是我们中途退出了,就不能保证这两个集合被merge到了一起。也就是说,此时退出,起点和终点之间还不一定有通路….所以,最正确的做法应该是起点和终点的parent都是一样的(两者在同一个union的充要条件)才退出。