C++无向图连通性问题[Tarjan求割边]—————Bridges

题目描述:

在赤壁之战中,曹操被诸葛亮和周瑜击败。但他不会放弃。曹操的军队仍然不善于水战,所以他提出了另一个想法。他在长江建造了许多岛屿,在这些岛屿的基础上,曹操的军队很容易攻击周瑜的部队。曹操还建造了连接岛屿的桥梁。如果所有岛屿都通过桥梁相连,那么曹操的军队可以在这些岛屿中非常方便地部署。周瑜无法忍受,所以他想要摧毁一些曹操的桥梁,这样一个或多个岛屿就会与其他岛屿分开。但周瑜只有一枚由诸葛亮留下的炸弹,所以他只能摧毁一座桥。周瑜必须派人携带炸弹来摧毁这座桥。桥上可能有守卫。轰炸队的士兵数量不能低于桥梁的守卫数量,否则任务就会失败。请弄清楚周瑜至少需要多少士兵。

输入:

测试用例不超过12个。 
在每个测试用例中: 
第一行包含两个整数N和M,意味着有N个岛和M个桥。所有岛都从1到N编号。(2 <= N <= 1000,0 

输出:

对于每个测试用例,输出周瑜完成任务所需的最少士兵数量。如果周瑜无法成功,请输出-1。

输入样例:

3 3
1 2 7
2 3 4
3 1 4
3 2
1 2 7
2 3 4
0 0

输出样例:

-1
4

思路分析:

其实这一题就是用Tanjar求割边,然后找花费的最小值的边。

主要是这几个特判情况。

假设图本身就不联通,那么就不要人。

如果没有割边,那么就没有答案。

最后一个就是割边的守卫为0,但是也要一人去炸。

代码实现:

#include
#include
#include
#include
using namespace std;
int n,m,low[1005],dfn[1005],cnt,a[1000005],p,ans;
bool iscut[1000005];
struct node{
	int to,nu,w;
	node(int To,int Nu,int W)
	{
		to=To;
		nu=Nu;
		w=W;
	}
};
vectorG[1005];
void Tarjan(int u,int fanu)
{
	cnt++;
	low[u]=cnt;
	dfn[u]=cnt;
	int child=0;
	for(int i=0;idfn[u])
			{
				iscut[vnu]=1;
				ans=min(ans,G[u][i].w);
			}
			low[u]=min(low[u],low[v]);
		}
		else if(dfn[u]>dfn[v]&&vnu!=fanu)
			low[u]=min(dfn[v],low[u]);
	}
}
int main()
{
	while(scanf("%d%d",&n,&m)!=-1&&n)
	{
		p=0;
		ans=0x3f3f3f3f;
		cnt=0;
		memset(low,0,sizeof(low));
		memset(dfn,0,sizeof(dfn));
		memset(a,0,sizeof(a));
		memset(iscut,0,sizeof(iscut));
		int a1,b,c;
		for(int i=1;i<=n;i++)
			G[i].clear();
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d%d",&a1,&b,&c);
			G[a1].push_back(node(b,i,c));
			G[b].push_back(node(a1,i,c));
		}
		for(int i=1;i<=n;i++)
		{
			if(!dfn[i])
			{
				p++;
				Tarjan(i,-1);
			}
		}
		if(p>1)
		{
			printf("0\n");
			continue;
		}
		if(ans==1061109567)
			printf("-1\n");
		else
			printf("%d\n",max(1,ans));
	}
}

 

你可能感兴趣的:(强连通分量)