True Liars POJ - 1417

제목: 좋은 사람 p1명, 나쁜 사람 좋은 사람 p2명, 나쁜 사람 좋은 사람 진실만 말하고 나쁜 사람 거짓말만 한다.
먼저 하나의 권한을 가지고 하나의 연결 블록 내의 관계를 조사하고 유지한 다음에 dp[i][j]는 전 i개의 연결 블록 안에 j개의 좋은 방안이 있다는 것을 나타낸다. 유일한 방안이기 때문에 출력 방안을 거꾸로 밀면 된다.
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define pb push_back
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d%d",&n,&m)
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define sld(n) scanf("%lld",&n)
#define sldd(n,m) scanf("%lld%lld",&n,&m)
#define slddd(n,m,k) scanf("%lld%lld%lld",&n,&m,&k)
#define sf(n) scanf("%lf",&n)
#define sff(n,m) scanf("%lf%lf",&n,&m)
#define sfff(n,m,k) scanf("%lf%lf%lf",&n,&m,&k)
#define ss(str) scanf("%s",str)
#define ansn() printf("%d
",ans)
#define lansn() printf("%lld
",ans)
#define r0(i,n) for(int i=0;i #define r1(i,e) for(int i=1;i<=e;++i) #define rn(i,e) for(int i=e;i>=1;--i) #define mst(abc,bca) memset(abc,bca,sizeof abc) #define lowbit(a) (a&(-a)) #define all(a) a.begin(),a.end() #define pii pair #define pll pair #define mp(aa,bb) make_pair(aa,bb) #define lrt rt<<1 #define rrt rt<<1|1 #define X first #define Y second #define PI (acos(-1.0)) typedef long long ll; typedef unsigned long long ull; typedef long double ld; //const ll mod = 1000000007 ; const double eps=1e-9; const int inf=0x3f3f3f3f; //const ll infl = 100000000000000000;//1e17 const int maxn= 3e2+20; const int maxm = 3e2+20; //muv[i]=(p-(p/i))*muv[p%i]%p; int in(int &ret) { char c; int sgn ; if(c=getchar(),c==EOF)return -1; while(c!='-'&&(c<'0'||c>'9'))c=getchar(); sgn = (c=='-')?-1:1; ret = (c=='-')?0:(c-'0'); while(c=getchar(),c>='0'&&c<='9')ret = ret*10+(c-'0'); ret *=sgn; return 1; } int fa[maxn<<1]; int d[maxn<<1]; int faf(int x) { if(fa[x]!=x) { int t = fa[x]; fa[x] = faf(t); d[x] = d[x]^d[t]; } return fa[x]; } void un(int a,int b,int c) { int f1 = faf(a),f2 =faf(b); if(f1!=f2) { fa[f2]=f1; d[f2] = d[a]^d[b]^c; } } vector<int>g[2][maxn<<1]; int num1[maxn<<1]; int num2[maxn<<1]; int dp[maxn<<1][maxn]; int rt[maxn<<1]; char s[100]; int main() { #ifdef LOCAL freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); #endif // LOCAL int n,p1,p2; while(~sddd(n,p1,p2),n||p1||p2) { r1(i,p1+p2)g[1][i].clear(),g[0][i].clear(),fa[i] = i,d[i] = 0,num1[i] = num2[i] = 0; while(n--) { int a,b; sdd(a,b); ss(s); if(s[0]=='n')un(a,b,1); else un(a,b,0); } for(int i=1;i<=p1+p2;++i) { int x = faf(i); if(d[i])++num1[x],g[1][x].pb(i); else ++num2[x],g[0][x].pb(i); } mst(dp,0); dp[0][0] = 1; int c = 0; for(int i=1;i<=p1+p2;++i) { if(faf(i)!=i)continue; rt[++c] = i; int mn = min(num1[i],num2[i]); for(int j=p1;j>=mn;--j) { if(dp[c-1][j-num1[i]]) dp[c][j]+=dp[c-1][j-num1[i]]; if(dp[c-1][j-num2[i]]) dp[c][j]+= dp[c-1][j-num2[i]]; } } if(dp[c][p1]!=1) { puts("no"); continue; } vector<int>v; while(c) { int r = rt[c]; if(dp[c-1][p1-num1[r]]==1) { int sz = g[1][r].size(); r0(i,sz) { v.pb(g[1][r][i]); } p1-=num1[r]; } else { int sz = g[0][r].size(); r0(i,sz)v.pb(g[0][r][i]); p1-=num2[r]; } c--; } sort(all(v)); int sz = v.size(); r0(i,sz) { int ans = v[i]; ansn(); } puts("end"); } return 0; }

좋은 웹페이지 즐겨찾기