Bonds
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 424 Accepted Submission(s): 203
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.
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.
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 1HintIn 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.
Author
FZU
Source
Recommend
题意:给出一幅点数极少的图,问每条边在多少个极小割之内。
解:去掉任意一个极小割之后对应两个连通块。
对于任意一条边的答案,用所有极小割的数量减去这条边所在连通块的数量即可。
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
#define mes(a,x,s) memset(a,x,(s)*sizeof a[0])
#define mem(a,x) memset(a,x,sizeof a)
#define ysk(x) (1<<(x))
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
const int maxn= 20 ;
const int maxm=200;
const int maxS=1048576;
int n,m,all,G[maxS+5],u[maxm+5],v[maxm+5],S,sum[maxS+5];
bool connected[maxS+3];
inline void add_edge(int ind,int x,int y)
{
u[ind]=x,v[ind]=y;
G[ysk(x)]|=ysk(y);
G[ysk(y)]|=ysk(x);
}
int lowbit(int x)
{
return x&(-x);
}
int main()
{
std::ios::sync_with_stdio(false);
int T,x,y,kase=0;cin>>T;
while(T--)
{
cin>>n>>m;
//得到邻接表(状压)
memset(G,0,sizeof G);
for0(i,m)
{
cin>>x>>y;
add_edge(i,x,y);
}
//最大状态
S=ysk(n)-1;
//对于每个点集s,得到能够到达的点集G[s]
for(int s=1;s<=S;s++)
{
int s2=s^lowbit(s);
G[s]=G[s2]|G[lowbit(s)];
}
//判断点集s是否连通
memset(connected,0,sizeof connected);
queue<int>q;
for0(i,n) q.push(ysk(i) ),connected[ysk(i)]=1;
while(!q.empty())
{
int x=q.front();q.pop();
int s=G[x]&(~x);//点集x可到达的点集 ,不包括x自身
while(s)
{
int s2=lowbit(s)|x;
if(!connected[s2])
{
connected[s2]=1;
q.push(s2);
}
s-=lowbit(s);
}
}
//初始化
all=0;
memset(sum,0,sizeof sum);
for1(s1,S-1)
{
int s2=S-s1;
if(s1<s2&&connected[s1]&&connected[s2] )//极小割,分割出去之后应该是正好两个连通块
{
sum[s1]++,sum[s2]++,all++;
}
}
//统计边集内的点共在多少个连通分量中出现。
//动态规划
for0(j,n)
{
for(int s=S-1;s;s--) if( !(s&ysk(j)) )
{
sum[s]+=sum[s|ysk(j) ];
}
}
//输出答案
printf("Case #%d:",++kase);
for0(i,m)
{
printf(" %d",all-sum[ ysk(u[i])|ysk(v[i]) ] );//所有极小割数量减去边i不在极小割内的数量。
}
putchar('\n');
}
return 0;
}