题目地址:
http://codeforces.com/problemset/problem/228/E
题意:
一幅图,100个点,最多10000条边,边权为0或1, 每次可以选择一个点,将与之相连的边取反(0变为1,1变为0) 问最后能不能将所有边变为1,若能,输出索取的点,否则,输出Impossible
思路:每个点只能选或不选,对于u-v 边,若是1,uv只能都选或都不选,若是0,只能u选时v不选,和v选时u不选
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
using namespace std;
typedef long long ll;
const int N = 1200;
vector<int>g[N];
int n,m;
bool mark[N];
int sta[N],top;
inline void add_edge(int u,int c1,int v,int c2)
{
u=2*(u-1)+c1,v=2*(v-1)+c2;
g[u].push_back(v);
g[v].push_back(u);
}
bool dfs(int u)
{
if(mark[u^1]) return false;
if(mark[u]) return true;
mark[u]=1;
sta[++top]=u;
int sz=g[u].size();
for(int i=0;i<sz;i++)
{
int v=g[u][i];
if(dfs(v)==false) return false;
}
return true;
}
bool judge()
{
for(int i=0;i<n;i++)
{
if(!mark[i]&&!mark[i^1])
{
top=0;
if(dfs(i)==false)
{
for(int j=1;j<=top;j++)
mark[sta[j]]=0;
top=0;
if(dfs(i^1)==false) return false;
}
}
}
return true;
}
void ini()
{
for(int i=0;i<n;i++) g[i].clear();
memset(mark,0,sizeof(mark));
top=0;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
n*=2;
ini();
for(int i=1;i<=m;i++)
{
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
if(c==0) add_edge(u,1,v,0),add_edge(u,0,v,1);
else add_edge(u,1,v,1),add_edge(u,0,v,0);
}
if(judge())
{
int cnt = 0;
for(int i=0;i<n;i+=2)
if(mark[i]) cnt++;
cout<<cnt<<endl;
for(int i=0;i<n;i+=2)
if(mark[i])printf("%d ",i/2+1);
}
else puts("Impossible");
}
return 0;
}