zoukankan      html  css  js  c++  java
  • [HDU5765]Bonds

    题面

    题意

    给出一张(n)(m)边无向连通图,求每条边出现在多少个割集中。
    (nle20,mlefrac{n(n-1)}{2})

    sol

    所谓割集,就是指把(n)个点分成两个集合后,两个集合分别都是连通的。
    所以我们可以预处理出每一个点集是否连通。
    考虑边((u,v))。实际上((u,v))要出现在割集中,(u,v)就必然在不同的点集中。
    来一波总方案减不合法
    所有可行的割的方案减去(u,v)在同一个割集里面的方案。
    (u,v)在同一个割集里面的方案实际上就是集合({u,v})的超集之和。高维前缀和搞一搞。

    前面那个预处理每个点集是否连通,使用(bfs)处理。
    处理出每个点集的相邻点集,每次(bfs)时候向外扩展一个节点,若未访问就丢到队列里面去。
    复杂度(O(nlog{n}))

    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define ll long long
    int gi()
    {
        int x=0,w=1;char ch=getchar();
        while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
        if (ch=='-') w=0,ch=getchar();
        while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return w?x:-x;
    }
    const int N = 1<<21;
    int T,n,m,all,u[500],v[500],reach[N],able[N],sum,tot[N];
    queue<int>Q;
    inline int lowbit(int k){return k&-k;}
    int main()
    {
    	T=gi();
    	for (int zsy=1;zsy<=T;++zsy)
    	{
    		n=gi();m=gi();all=(1<<n)-1;sum=0;
    		memset(reach,0,sizeof(reach));
    		memset(able,0,sizeof(able));
    		memset(tot,0,sizeof(tot));
    		for (int i=1;i<=m;++i)
    		{
    			u[i]=gi();v[i]=gi();
    			reach[1<<u[i]]|=1<<v[i];
    			reach[1<<v[i]]|=1<<u[i];
    		}
    		for (int i=0;i<=all;++i)
    			reach[i]=reach[lowbit(i)]|reach[i^lowbit(i)];
    		for (int i=0;i<n;++i)
    			Q.push(1<<i),able[1<<i]=1;
    		while (!Q.empty())
    		{
    			int u=Q.front();Q.pop();
    			int tmp=reach[u];
    			while (tmp)
    			{
    				int v=u|lowbit(tmp);
    				if (!able[v]) able[v]=1,Q.push(v);
    				tmp^=lowbit(tmp);
    			}
    		}
    		for (int i=0;i<=all;++i)
    			if (able[i]&&able[i^all])
    				++sum,++tot[i];
    		sum>>=1;
    		for (int j=0;j<n;++j)
    			for (int i=all;i>=0;--i)
    				if ((i&(1<<j))==0) tot[i]+=tot[i|(1<<j)];
    		printf("Case #%d:",zsy);
    		for (int i=1;i<=m;++i)
    			printf(" %d",sum-tot[(1<<u[i])|(1<<v[i])]);
    		puts("");
    	}
    }
    
  • 相关阅读:
    2 浮点数
    1 有符号与无符号
    4.变量和不同的赋值方式
    文档格式标准
    常用mysql命令
    一个简单的jsp+servlet实例,实现简单的登录
    容量调度器与公平调度器区别
    CListCtrl用法总结(二)
    CListCtrl 实现排序功能(数字和字母)
    CString 转换成 char *
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8460378.html
Copyright © 2011-2022 走看看