zoukankan      html  css  js  c++  java
  • CF_400_D

    codeforces_400_D

    题目大意:给出n扇门,m把钥匙,和没把钥匙可以改变状态(关->开,开->关》)的门的数量及对应编号(保证每个门被两把钥匙控制),现给出n扇门的初始状态(1表示开,0表示关),问是否可以通过这m把钥匙(可用可不用,不一定用完)使得所有的门都开启。
    题解:终于看到了2-sat的能想出来的题了,2-sat本质是满族解的判断,这题显然可以用2-sat来求解,求解的一般套路是将每个点拆为两个点,分别表示取或者不取(即一件事的正反两面),最后通过2-sat算法,判断是否可行。这题需要一个转化,即我们对m拆点,表示用或者不用这把钥匙改变对应的门。那么如何连边?可以这样想:对于一个门 的初始状态,如果是开,那么两把钥匙要么都用,要么都不用;如果是关,一定是用一把弃一把。那么就是说连边是要用门的初始状态确定的,那么这题也就解决了。

    #pragma comment(linker, "/STACK: 1024000000,1024000000")
    #include <bits/stdc++.h>
    #define pb push_back
    #define mp make_pair
    #define eb emplace_back
    #define em emplace
    #define pii pair<int,int>
    #define de(x) cout << #x << " = " << x << endl
    #define clr(a,b) memset(a,b,sizeof(a))
    #define INF (0x3f3f3f3f)
    #define LINF ((long long)(0x3f3f3f3f3f3f3f3f))
    #define F first
    #define S second
    using namespace std;
    inline int getint()
    {
      int _x=0; char _tc=getchar();
      while(_tc<'0'||_tc>'9') _tc=getchar();
      while(_tc>='0'&&_tc<='9') _x*=10,_x+=(_tc-'0'),_tc=getchar();
      return _x;
    }
    
    const int N = 1e5 + 15;
    int n, m;
    int dor[N];
    vector<int> key[N];
    
    struct TwoSet
    {
    	static const int MAXV = 100100;
    	int V, n, tp, S[MAXV<<1];
    	vector<int> g[MAXV<<1];
    	bool vis[MAXV<<1];
    	
    	void init( int tt )
    	{
    		n = tt;
    		V = (tt<<1) + 1;
    		for ( int i = 1; i <= V; i ++ )
    			g[i].clear(), vis[i] = false;
    	}
    	void addEdge( int x, int y )
    	{
    		g[x].pb(y);
    		g[y].pb(x);
    	}
    	bool dfs( int x )
    	{
    		if ( vis[ x > n ? x - n : x + n ] ) return false;
    		if ( vis[x] ) return true;
    		vis[ S[++tp] = x ] = 1;
    		for ( int v : g[x] )
    			if ( !dfs(v) ) return false;
    		return true;
    	}
    			
    	bool solve()
    	{
    		for ( int i = 1; i <= n; i ++ )
    			if ( !vis[i] && !vis[i+n] )
    			{
    				tp = 0;
    				if ( !dfs(i) )
    				{
    					while ( tp ) vis[S[tp--]] = false;
    					if ( !dfs(i+n) ) return false;
    				}
    			}
    		return true;
    	}
    }TwoSet;
    
    int main()
    {
    	scanf("%d%d", &n, &m);
    	for ( int i = 1; i <= n; i ++ )
    		scanf("%d", &dor[i]);
    	for ( int i = 1, x; i <= m; i ++ )
    	{
    		scanf("%d", &x);
    		for ( int j = 0, y; j < x; j ++ )
    			scanf("%d", &y), key[y].pb(i);
    	}
    	TwoSet.init(m);
    	for ( int i = 1, x, y; i <= n; i ++ )
    	{
    		x = key[i][0], y = key[i][1];
    		if ( !dor[i] )
    		{
    			TwoSet.addEdge(x,y+m);
    			TwoSet.addEdge(x+m,y);
    		}
    		else
    		{
    			TwoSet.addEdge(x,y);
    			TwoSet.addEdge(x+m,y+m);
    		}
    	}
    	if ( TwoSet.solve() ) puts("YES");
    	else puts("NO");
    	return 0;
    }
    
  • 相关阅读:
    vue
    Html5的本地储存 Web Storage
    java json解析(转)
    Python常用字符编码(转)
    特殊符号集锦(转)
    neo4j性能调优(转)
    hadoop fs -text和hadoop fs -cat的区别(转)
    docker和dockerfile极简入门(转)
    docker原理(转)
    neo4j配置(转)
  • 原文地址:https://www.cnblogs.com/FormerAutumn/p/10433357.html
Copyright © 2011-2022 走看看