Codeforces Gym100650E: Reliable Nets

本文介绍了Codeforces Gym100650E问题,目标是设计一个即使断开一条边也能保持所有建筑间通信的最便宜的校园网络。题目提供输入输出格式、样例输入输出,并解析了题意,提出通过状压和Tarjan算法寻找最小成本的可靠网络。
摘要由CSDN通过智能技术生成

Problem E: Reliable Nets

You’re in charge of designing a campus network between buildings and are very worried about its reliability and its cost. So, you’ve decided to build some redundancy into your network while keeping it as inexpensive as possible. Specifically, you want to build the cheapest network so that if any one line is broken, all buildings can still communicate. We’ll call this a minimal reliable net.

Input

There will be multiple test cases for this problem. Each test case will start with a pair of integers n(15) and m(20) on a line indicating the number of buildings (numbered 1 through n) and the number of potential inter-building connections, respectively. (Values of n = m = 0 indicate the end of the problem.) The following m lines are of the form b1 b2 c (all positive integers) indicating that it costs c to connect building b1 and b2. All connections are bidirectional.

Output

For each test case you should print one line giving the cost of a minimal reliable net. If there is a minimal reliable net, the output line should be of the form:
The minimal cost for test case p is c.
where p is the number of the test case (starting at 1) and c is the cost. If there is no reliable net possible, output a line of the form:
There is no reliable net possible for test case p.

Sample Input

4 5
1 2 1
1 3 2
2 4 2
3 4 1
2 3 1
2 1
1 2 5
0 0

Sample Output

The minimal cost for test case 1 is 6.
There is no reliable net possible for test case 2.

题意

给出一些点和一些边,每条边有花费,要求选择一部分边,构成一个去掉任意一条边后仍然连通的图,并且花费最小。

题解

点和边的数量很少,可以状压去暴力,每次枚举选择的边,之后跑tarjan找桥,更新ans值即可。

代码

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#define fout freopen("out.txt","w",stdout)
#define fin freopen("in.txt","r",stdin)

using namespace std;

int m,n;
int ans;
int cas=1;
int MAX;
int G[25][25];
int Enum[20];
struct edge
{
    int u,v,c;
};
edge E[25];
int dfn[20],low[20],vis[25];
int T;
int status;
int cbit(int t)
{
    int x=0;
    while(t)
    {
        x+=t&1;
        t>>=1;
    }
    return x;
}
int calc(int t)
{
    int x=0;
    for(int i=0;i<m;i++)
    {
        if(status&(1<<i))
            x+=E[i].c;
    }
    return x;
}
int dfs(int x)
{
    if(dfn[x])
        return dfn[x];
    low[x]=dfn[x]=T++;
    for(int i=0;i<Enum[x];i++)
    {
        if(vis[G[x][i]]==0&&((1<<G[x][i])&status))
        {
            vis[G[x][i]]=1;
            low[x]=min(low[x],dfs(x==E[G[x][i]].u?E[G[x][i]].v:E[G[x][i]].u));
        }
    }
    return low[x];
}
int main()
{
    while(scanf("%d%d",&n,&m)==2&&n&&m)
    {
        MAX=1<<m;
        ans=1000000000;
        memset(Enum,0,sizeof Enum);
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].c);
            G[E[i].u][Enum[E[i].u]++]=i;
            G[E[i].v][Enum[E[i].v]++]=i;
        }
        if(m<n)
        {
            printf("There is no reliable net possible for test case %d.\n",cas++);
            continue;
        }
        for(status=0;status<MAX;status++)
        {
            if(cbit(status)<n)
                continue;
            T=1;
            memset(dfn,0,sizeof dfn);
            memset(low,0,sizeof low);
            memset(vis,0,sizeof vis);
            for(int i=1;i<=n;i++)
            {
                if(dfn[i]==0)
                {
                    dfs(i);
                    break;
                }
            }
            int flag=0;
            for(int i=1;i<=n;i++)
            {
                if(dfn[i]==0)
                {
                    flag=1;
                    break;
                }
            }
            if(flag)
                continue;
            for(int i=0;i<m;i++)
            {
                if(((1<<i)&status)&&((dfn[E[i].u]>dfn[E[i].v]&&low[E[i].u]>dfn[E[i].v])||(dfn[E[i].v]>dfn[E[i].u]&&low[E[i].v]>dfn[E[i].u])))
                {
                    flag=1;
                    break;
                }
            }
            if(flag)
                continue;
            ans=min(ans,calc(status));
        }
        if(ans==1000000000)
            printf("There is no reliable net possible for test case %d.\n",cas++);
        else
            printf("The minimal cost for test case %d is %d.\n",cas++,ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值