题意:给出一幅点数极少的图,问每条边在多少个极小割之内。
解:去掉任意一个极小割之后对应两个连通块。
对于任意一条边的答案,用所有极小割的数量减去这条边所在连通块的数量即可。
#include
#include
#include
#include
#include
#include
#include
#include
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 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);
queueq;
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