標籤:
題意:給一個圖,找一棵產生樹,其滿足:最大權-最小權=最小。簡單圖,不一定連通,權值可能全相同。
思路:點數量不大。根據kruscal每次挑選的是最小權值的邊,那麼苗條度一定也是最小。但是產生樹有多棵,苗條度自然也有多個,窮舉下所有產生樹,就知道了結果了。根據“只要起始邊不同,產生樹必定不同”來窮舉起始邊。
又發現一可能的坑!!我以為LONG_MAX就是int的正最大值,也就是2147483647=2^31-1,在我的機器上也許如此,在OJ上不一定了,用LONG_MAX轉int會不同,得注意。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N=100+5; 4 const int INF=0x7f7f7f7f; 5 int g[N][N]; 6 int n, m; 7 int pre[N]; 8 vector< pair<int,int> > vect; 9 inline int cmp(pair<int,int> a,pair<int,int> b)10 {11 return g[a.first][a.second]<g[b.first][b.second]? true: false;12 }13 14 int find(int x)15 {16 return pre[x]==x? x: pre[x]=find(pre[x]);17 }18 void joint(int a,int b)19 {20 a=find(a);21 b=find(b);22 if(a!=b) pre[a]=b;23 }24 25 26 int kruscal(int i)27 {28 int q=vect[i].first;29 int p=vect[i].second;30 int cnt=0;31 for(int i=0; i<=n; i++) pre[i]=i;32 33 for(int j=i; j<m; j++)34 {35 int a=vect[j].first;36 int b=vect[j].second;37 if(find(a)!=find(b))38 {39 cnt++;40 if(cnt==n-1) return g[a][b]-g[q][p];41 joint(a,b);42 }43 }44 return INF;45 }46 47 int cal()48 {49 if(m<n-1 || kruscal(0)==INF) return -1;//不連通50 51 sort(vect.begin(), vect.end(), cmp);52 int ans=INF;53 for(int i=0; i<m; i++)54 {55 int q=kruscal(i);56 if(q==INF) continue;57 ans=min(ans,q);58 }59 return ans;60 }61 62 int main()63 {64 //freopen("input.txt", "r", stdin);65 int a, b, w;66 while(scanf("%d%d",&n,&m), n+m )67 {68 memset(g,0,sizeof(g));69 vect.clear();70 for(int i=0; i<m; i++)71 {72 scanf("%d%d%d",&a,&b,&w);73 g[a][b]=g[b][a]=w;74 vect.push_back(make_pair(b,a));75 }76 cout<<cal()<<endl;77 }78 return 0;79 }AC代碼
UVA 1395 Slim Span (最小產生樹,MST,kruscal)