Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

不晓得我的方法为什么不用特判。。kruscal。。代码。。比较丑

Posted by 201151122 at 2013-05-11 21:24:02 on Problem 1679
#include <iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAX 9999999
using namespace std;

const int maxn=100+10;
const int maxm=maxn*maxn/2+10;

struct Edge
{
    int x,y,w;
    int del;//删边
    int equal;//是否存在权值相等的边
    int used;//记录第一次用过的边
}e[maxm];

int father[maxn];
int sum,n,m;
bool first,ok;

void make_set()//初始化
{
    for(int i=1;i<=n;i++)father[i]=i;
}

int find_set(int x)//并查集的查找
{
    if(x!=father[x])
    father[x]=find_set(father[x]);
    return father[x];
}

void union_set(int x,int y,int w,int i)//并查集的并操作
{
    int a=find_set(x);
    int b=find_set(y);
    if(a==b)return ;
    else father[a]=b;
    sum+=w;
    if(first)e[i].used=1;//将选过的边标记
}

bool cmp(const Edge &a,const Edge &b)
{
    return a.w<b.w;
}

int kruscal()//做一次kruscal
{
    make_set();
    sort(e,e+m,cmp);
    sum=0;
    for(int i=0;i<m;i++)
    {
        if(e[i].del==1)continue;//如果该边已删除,不选
        union_set(e[i].x,e[i].y,e[i].w,i);
    }
    return sum;
}

void cal_equal()//判断所给的边中是否存在权值相同的边,并标记
{
    for(int i=0;i<m;i++)
    for(int j=i+1;j<m;j++)
    {
        if(e[i].w==e[j].w)
        e[i].equal=e[j].equal=1;
    }
}

int main()
{
    freopen("in","r",stdin);
    int t,xx,yy,ww;
    cin>>t;
    while(t--)
    {
        scanf("%d %d",&n,&m);
        for(int i=0;i<m;i++)//初始化
        {
            scanf("%d %d %d",&xx,&yy,&ww);
            e[i].x=xx;
            e[i].y=yy;
            e[i].w=ww;
            e[i].del=0;
            e[i].equal=0;
            e[i].used=0;
        }
        cal_equal();//计算
        first=true; //做第一次kruscal

        int weight1=kruscal(),weight2;

        first=ok=false;ok表示是否唯一
 
       //扫描每条边,如果该边在第一次中用过,并且存在于该边权值相同的边,将该边删去,重新做一次kruscal,判断
        for(int i=0;i<m;i++)
        {
            if(e[i].used&&e[i].equal)
            {
                e[i].del=1;
                weight2=kruscal();
                if(weight1==weight2)
                {
                    ok=true;
                    break;
                }
                e[i].del=0;//如果不是,则还原该边
            }
        }
        if(ok)
        printf("Not Unique!\n");
        else printf("%d\n",weight1);
    }
    return 0;
}

Followed by:

Post your reply here:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator