二分答案 + 2-SAT判断
#include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<algorithm> using namespace std; const int maxn=8000+5; int M,N,T; int ans; int L,R,Mid; int a[10010],b[10010],c[10010]; struct TwoSAT { int n; vector<int> G[maxn*2]; bool mark[maxn*2]; int S[maxn*2],c; bool dfs(int x) { if(mark[x^1]) return false; if(mark[x]) return true; mark[x]=true; S[c++]=x; for(int i=0;i<G[x].size();i++) if(!dfs(G[x][i])) return false; return true; } void init(int n) { this->n=n; for(int i=0;i<n*2;i++) G[i].clear(); memset(mark,0,sizeof mark); } void add_clause(int x,int y) { G[x].push_back(y^1); G[y].push_back(x^1); } bool solve() { for(int i=0;i<2*n;i+=2) if(!mark[i]&&!mark[i+1]) { c=0; if(!dfs(i)) { while(c>0) mark[S[--c]]=false; if(!dfs(i+1)) return false; } } return true; } }; int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&N,&M); for(int i=0;i<M;i++) scanf("%d%d%d",&a[i],&b[i],&c[i]); L=0,R=M; while(L<=R) { Mid=(L+R)/2; TwoSAT T; T.init(N); for(int i=0;i<Mid;i++) { if(c[i]==2) { T.add_clause(2*a[i]+1,2*b[i]+1); } else if(c[i]==1) { T.add_clause(2*a[i]+1,2*b[i]); T.add_clause(2*a[i],2*b[i]+1); } else if(c[i]==0) { T.add_clause(2*a[i],2*b[i]); } } if(T.solve()) { ans=Mid; L=Mid+1; } else R=Mid-1; } printf("%d\n",ans); } return 0; }
时间: 2024-10-09 17:01:18