BNUOJ-26586 Simon the Spider 最小生成树+枚举

  题目链接:http://www.bnuoj.com/bnuoj/problem_show.php?pid=26586

  题意:给一个图,每条边有一个权值。要你求选择一棵树,权值和为sum,然后在树上选择一条边权值为w,然后使得sum-2*w最小。

  首先求一遍最小生成树,然后求出每两个点之间的最小瓶颈路,然后枚举边就行了。。  

  1 //STATUS:C++_AC_916MS_30048KB

  2 #include <cmath>

  3 #include <cstdio>

  4 #include <cstring>

  5 #include <iostream>

  6 #include <algorithm>

  7 using namespace std;

  8 #define mem(a,b) memset(a,b,sizeof(a))

  9 typedef long long LL;

 10 

 11 const int N=2010;

 12 

 13 struct Edge{

 14     int u,v,w;

 15 }e[1000010],et[2000010];

 16 int first[N],next[2000010];

 17 int p[N],vis[N],d[N][N];

 18 bool mst[1000010];

 19 int n,m,mt;

 20 

 21 void adde(int a,int b,int c)

 22 {

 23     et[mt].u=a,et[mt].v=b,et[mt].w=c;

 24     next[mt]=first[a];first[a]=mt++;

 25     et[mt].u=b,et[mt].v=a,et[mt].w=c;

 26     next[mt]=first[b];first[b]=mt++;

 27 }

 28 

 29 int cmp(const Edge& a,const Edge& b)

 30 {

 31     return a.w<b.w;

 32 }

 33 

 34 int find(int x){return p[x]==x?x:p[x]=find(p[x]);}

 35 

 36 int Kruskal()

 37 {

 38     int i,j,x,y,sum=0,cnt=0;

 39     for(i=1;i<=n;i++)p[i]=i;

 40     sort(e,e+m,cmp);

 41     mem(mst,0);

 42     for(i=0;i<m;i++){

 43         x=find(e[i].u);

 44         y=find(e[i].v);

 45         if(x!=y){

 46             cnt++;

 47             sum+=e[i].w;

 48             p[y]=x;

 49             mst[i]=true;

 50         }

 51     }

 52     if(cnt<n-1)return -1;

 53     return sum;

 54 }

 55 

 56 int dfs(int& s,int u,int fa,int hig)

 57 {

 58     int i,v;

 59     for(i=first[u];i!=-1;i=next[i]){

 60         v=et[i].v;

 61         if(v==fa)continue;

 62         d[s][v]=max(hig,et[i].w);

 63         dfs(s,v,u,d[s][v]);

 64     }

 65     return 0;

 66 }

 67 

 68 int main(){

 69  //   freopen("in.txt","r",stdin);

 70     int i,j;

 71     while(~scanf("%d%d",&n,&m))

 72     {

 73         for(i=0;i<m;i++){

 74             scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);

 75         }

 76 

 77         int sum;

 78         if((sum=Kruskal())==-1){

 79             printf("disconnected\n");

 80             continue;

 81         }

 82         mem(first,-1);mt=0;

 83         for(i=0;i<m;i++){

 84             if(mst[i]){

 85                 adde(e[i].u,e[i].v,e[i].w);

 86             }

 87         }

 88         mem(d,0);

 89         for(i=1;i<=n;i++){

 90             dfs(i,i,-1,0);

 91         }

 92         int ans=0x7FFFFFFF;

 93         for(i=0;i<m;i++){

 94             ans=min(ans,sum-d[e[i].u][e[i].v]-e[i].w);

 95         }

 96 

 97         printf("%d\n",ans);

 98     }

 99     return 0;

100 }

 

你可能感兴趣的:(spider)