Ural 1709. Penguin-Avia

来源:互联网 发布:计算机算法有哪些 编辑:程序博客网 时间:2024/06/07 13:41

http://acm.timus.ru/problem.aspx?space=1&num=1709


题意:给定一个有若干条边的无向图,删除和增加边的代价分别为da,求若使该图成为一棵树最小代价是多少。


解法:首先要把图的每一个强联通分量删成树,然后再把每棵树连起来即可。对于第一步,采用染色法。任取一个没有被染色的点,dfs由该点可到达的点,标记可到点表示为同一强联通分量,并且标记所经历的边。如果两点有相同标记且之间的边未被标记的话,则该边可删去。连树的话,从第一个点分别向其它树任意一点连一条边即可。


#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<cmath>#include<set>#include<map>#include<vector>#define N 105using namespace std;int maps[N][N],tp[N],n,d,a;long long ans;void col(int x,int c){    int i;    for (i=1;i<=n;i++)    if (maps[x][i]==1)    {        if (tp[i]==0)        {            tp[i]=c;            maps[x][i]=maps[i][x]=4;            col(i,c);        }        else        {            ans+=d;            maps[x][i]=maps[i][x]=3;        }    }}int main(){    freopen("a","r",stdin);    int i,j,c;    ans=0;    char s[200];    scanf("%d",&n);    scanf("%d%d",&d,&a);    memset(maps,0,sizeof(maps));    gets(s);    for (i=1;i<=n;i++)    {        gets(s);        for (j=0;j<n;j++) maps[i][j+1]=s[j]-'0';    }    for (i=1;i<=n;i++) tp[i]=0;    c=0;    for (i=1;i<=n;i++)    if (tp[i]==0)    {        c++;        tp[i]=c;        col(i,c);    }    bool tp1[N];    for (i=1;i<=c;i++) tp1[i]=false;    tp1[1]=true;    for (i=2;i<=n;i++)    if (tp[i]!=tp[1] && tp1[tp[i]]==false)    {        maps[i][1]=maps[1][i]=2;//a        ans+=a;        tp1[tp[i]]=true;    }    printf("%lld\n",ans);    for (i=1;i<=n;i++)    {        for (j=1;j<=n;j++)        if (maps[i][j]==2) printf("a");        else if (maps[i][j]==3) printf("d");        else printf("0");        printf("\n");    }    return 0;}


原创粉丝点击