201703-4地鐵修建 終於找到WA點
阿新 • • 發佈:2018-12-15
修改後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的充要條件)才退出。