POJ 2421 Constructing Roads 最小生成樹
題意:還是給你n個點,然後求最小生成樹。特殊之處在於有一些點之間已經連上了邊。
思路:對於已經有邊的點,特殊標記一下,加邊的時候把這些邊的權值賦值為0即可。這樣就可以既保證這些邊一定存在,又保證了所求的結果正確。
代碼:
- #include
- #include
- #include
- #include
- #include
- using namespace std;
-
- #define CLR(arr,val) memset(arr,val,sizeof(arr))
- const int N = 110;
- int father[N];
- struct edge{
- int lp,rp,value;
- }ee[N*N];
- int map[N][N],flag[N][N],numedge,n;
- bool cmp(edge a,edge b){
- return a.value < b.value;
- }
- int find(int x){
- if(x == father[x])
- return father[x];
- return find(father[x]);
- }
- bool Union_Set(int x,int y){
- int fx = find(x);
- int fy = find(y);
- if(fx == fy){
- return false;
- }
- else{
- father[fx] = fy;
- return true;
- }
- }
- int kruskal(){
- sort(ee,ee+numedge,cmp);
- for(int i = 1; i <= n; ++i)
- father[i] = i;
- int sum = 0;
- for(int i = 0; i < numedge; ++i){
- int lx = ee[i].lp;
- int rx = ee[i].rp;
- if(Union_Set(lx,rx)){
- sum += ee[i].value;
- }
- }
- return sum;
- }
- int main(){
- //freopen(1.txt,r,stdin);
- while(scanf(%d,&n) != EOF){
- CLR(flag,0);
- for(int i = 1; i <= n; ++i){
- for(int j = 1; j <= n; ++j)
- scanf(%d,&map[i][j]);
- }
- int m,x,y;
- scanf(%d,&m);
- while(m--){
- scanf(%d%d,&x,&y);
- flag[x][y] = 1;
- }
- numedge = 0;
- for(int i = 1; i < n; ++i){
- for(int j = i + 1; j <= n; ++j){
- if(flag[i][j]){
- ee[numedge].lp = i;
- ee[numedge].rp = j;
- ee[numedge].value = 0;
- numedge++;
- }
- else{
- ee[numedge].lp = i;
- ee[numedge].rp = j;
- ee[numedge].value = map[i][j];
- numedge++;
- }
- }
- }
- int ans = kruskal();
- printf(%d ,ans);
- }
- return 0;
- }