/**
題目:刪去一個點,然后求出需要增加最小代價的邊集合生成連通圖
思路:
prim+最小堆
1.之前圖中未破壞的邊必用,從而把兩兩之間可互達的點集合 合並成一個點
2.求出不同點集合的最短距離,用prim+最小堆求出最小生成樹
kruskal
1.之前圖中未破壞的邊必用,全部加到圖中
2.途中被破壞的邊按照邊權從小到大的順序依次加入圖中,直到圖變為連通圖
兩個方法的對應一個點的最小生成樹的復雜度都是nlogm,第二個方法較好寫
優化:
1.未破壞的邊直接加入圖中
2.當有n-2條邊(當前刪去一個點后,圖中n-1個點)在圖中時,直接結束建生成樹
另外:
求圖的連通性:
有向 強連通
無向 並查集
當然,並查集好寫很多。。。
**/
1 #include <stdio.h> 2 #include <stdlib.h> 3 #define maxn 500 4 #define maxm 125000 5 #define maxdist 100000 6 7 /** 8 題目:刪去一個點,然后求出需要增加最小代價的邊集合生成連通圖 9 思路: 10 prim+最小堆 11 1.之前圖中未破壞的邊必用,從而把兩兩之間可互達的點集合 合並成一個點 12 2.求出不同點集合的最短距離,用prim+最小堆求出最小生成樹 13 14 kruskal 15 1.之前圖中未破壞的邊必用,全部加到圖中 16 2.途中被破壞的邊按照邊權從小到大的順序依次加入圖中,直到圖變為連通圖 17 18 兩個方法的對應一個點的最小生成樹的復雜度都是nlogm,第二個方法較好寫 19 20 優化: 21 1.未破壞的邊直接加入圖中 22 2.當有n-2條邊(當前刪去一個點后,圖中n-1個點)在圖中時,直接結束建生成樹 23 24 另外: 25 求圖的連通性: 26 有向 強連通 27 無向 並查集 28 29 當然,並查集好寫很多。。。 30 **/ 31 32 struct node 33 { 34 long x,y,c,s; 35 }edge0[maxm+1],edge1[maxm+1]; 36 long fa[maxn+1]; 37 38 long max(long a,long b) 39 { 40 if (a>b) 41 return a; 42 else 43 return b; 44 } 45 46 int cmp(const void *a,const void *b) 47 { 48 //先把未損壞的路徑加入圖中 49 if ((*(struct node *)a).s < (*(struct node *)b).s) 50 return 1; 51 else if ((*(struct node *)a).s > (*(struct node *)b).s) 52 return -1; 53 //再對已損壞的路徑進行排序,用kruskal算法,m log m 54 else if ((*(struct node *)a).c < (*(struct node *)b).c) 55 return 1; 56 else 57 return -1; 58 } 59 60 long getfather(long d) 61 { 62 if (fa[d]==d) 63 return d; 64 else 65 return getfather(fa[d]); 66 } 67 68 int main() 69 { 70 long i,j,n,m,p,q,x,y,c,s,g,fx,fy,ans,cost[maxn+1]; 71 while (scanf("%ld%ld",&n,&m)!=EOF) 72 { 73 p=0; 74 q=0; 75 for (i=0;i<m;i++) 76 { 77 scanf("%ld%ld%ld%ld",&x,&y,&c,&s); 78 if (s==1) 79 { 80 p++; 81 edge1[p].x=x; edge1[p].y=y; edge1[p].c=c; edge1[p].s=s; 82 } 83 else 84 { 85 q++; 86 edge0[q].x=x; edge0[q].y=y; edge0[q].c=c; edge0[q].s=s; 87 } 88 } 89 qsort(edge0+1,q,sizeof(struct node),cmp); 90 91 ans=0; 92 for (i=1;i<=n;i++) 93 { 94 for (j=1;j<=n;j++) 95 fa[j]=j; 96 g=0; 97 //edge - exist 98 for (j=1;j<=p;j++) 99 { 100 if (edge1[j].x==i || edge1[j].y==i) continue; 101 fx=getfather(edge1[j].x); 102 fy=getfather(edge1[j].y); 103 if (fx==fy) continue; 104 fa[fx]=fy; 105 g++; 106 if (g==n-2) 107 break; 108 } 109 //優化 110 if (g==n-2) 111 { 112 cost[i]=0; 113 continue; 114 } 115 116 //edge - not exist 117 cost[i]=0; 118 for (j=1;j<=q;j++) 119 { 120 if (edge0[j].x==i || edge0[j].y==i) continue; 121 fx=getfather(edge0[j].x); 122 fy=getfather(edge0[j].y); 123 if (fx==fy) continue; 124 fa[fx]=fy; 125 g++; 126 cost[i]+=edge0[j].c; 127 //優化 128 if (g==n-2) 129 break; 130 } 131 if (g<n-2) 132 cost[i]=maxdist; 133 ans=max(ans,cost[i]); 134 } 135 if (ans>0) 136 { 137 for (i=1;i<=n;i++) 138 if (cost[i]==ans) 139 { 140 printf("%ld",i); 141 break; 142 } 143 for (j=i+1;j<=n;j++) 144 if (cost[j]==ans) 145 printf(" %ld",j); 146 printf("\n"); 147 } 148 else 149 printf("0\n"); 150 } 151 return 0; 152 }