1. 程式人生 > >201703-4地鐵修建 終於找到WA點

201703-4地鐵修建 終於找到WA點

修改後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的充要條件)才退出。