Hdu-5765 Bonds(状压)


Problem Description
Given an undirected connected graph with N points and M edges. ?? wants to know the number of occurrence in all bonds of graph for every edge.The index of points starts from 0.
An edge cut E of a Graph G is a set of edges of G and the G would be disconnected after deleting all the edges of E.
A bond of a graph is an edge cut does not have any other edge cut as a proper subset.


 

Input
The first line of the input gives the number of test cases T; T test cases follow.
Each test case consists of two integers: N, M, followed by M lines, each line contains two integers u, v, implying an undirected edge between u and v.

limits
T <= 20
2 <= N <= 20
N-1 <= M <= N*(N-1)/2
Edges are distinct.
No edge connects to the point itself.
N is larger than 10 in no more than 5 cases.
 

Output
For each test case output “Case #x: y1 y2 … yN” (without quotes), where x is the test case number (starting from 1), and yi is the occurrence times in all bonds of i-th edge.
 

Sample Input
  
  
2 3 3 0 1 0 2 1 2 3 2 0 1 0 2
 

Sample Output
  
  
Case #1: 2 2 2 Case #2: 1 1
Hint
In first case, {(0,1),(0,2)} , {(0,1),(1,2)} , {(0,2),(1,2)} are bonds. In second case, {(0,1)},{(0,2)} is bond.
分析:点数很少,根据bonds的定义它一定是把原图分成两个联通块,那么我们枚举一下原图的连通子集个数除以二就是全图的bonds数量,然后对于每个询问,我们求一下不包含这条边两端的连通块数量再减去就行了。
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
#define INF 0x3f3f3f3f
#define eps 1e-9
#define MAXN 10005
using namespace std;
int T,n,m;
struct Edge
{
	int u,v;
}edge[500];
int number[2000000],zy[22],e[22],cnt[2000000];
int main()
{
	for(int i = 1;i <= (1<<20)-1;i++) number[i] = number[i&(i-1)] + 1;
	for(int i = 0;i <= 20;i++) zy[i] = 1<<i;
	scanf("%d",&T);
	for(int t = 1;t <= T;t++)
	{
		memset(e,0,sizeof(e));
		memset(cnt,0,sizeof(cnt));
		scanf("%d%d",&n,&m);
		for(int i = 1;i <= m;i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			edge[i].u = ++u;
			edge[i].v = ++v;
			e[u] += zy[v-1];
			e[v] += zy[u-1];
		}
		for(int i = 1;i <= zy[n] - 1;i++)
		 if(number[i] == 1) cnt[i] = true;
		 else 
		 {
			for(int k = 1;k <= n;k++) 
		   	 if((i & zy[k-1]) && cnt[i ^ zy[k-1]] && (e[k] & i) != 0)
		   	 {
		   	 	cnt[i] = true;
				break;	
			 }
		 } 
		printf("Case #%d:",t);
		int tot = 0;
		for(int i = 1;i < zy[n]-1;i++) 
		 if(cnt[i] && cnt[zy[n]-1-i]) tot++;
		for(int i = 1;i <= m;i++)
		{
			int ans = 0,u = edge[i].u,v = edge[i].v;
			for(int j = zy[n]-1-zy[u-1]-zy[v-1];j;j = (zy[n]-1-zy[u-1]-zy[v-1])&(j-1))
			 if(cnt[j] && cnt[zy[n]-1-j]) ans++;
			printf(" %d",tot/2-ans);
		}
		printf("\n");
	}	
} 




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值