也是很裸的模型,不过由于解未知,要求找到最大的可行解,所以需要在解的可行区间里面二分查找答案,直到找到最大的可行解。
if dep < m and x[a[dep]] + x[b[dep]] != c[dep] then go(dep + 1, n, m)
我们在 0 到 m 上查找最大可行解时,要想让 dep 值尽量大,就要尽量满足不等式(x[ a[ dep ] ] + x[ b[ dep ] ] != c[ dep ]),c[ dep ]值有三种情况,如下:
if(c[i]==0) //x[ a[i] ],x[ b[i] ]不能同时为0
else if(c[i]==1) //x[ a[i] ],x[ b[i] ]不能不同,二者要么同时为0,要么同时为1
else if(c[i]==2) //x[ a[i] ],x[ b[i] ]不能同时为1
根据这个关系建图,就好了。
#include<cstdio>
#include<cstring>
#include<STACK>
#include<climits>
using namespace std;
const int N = 20010;
struct Edge{
int s,e,next;
}edge[3*N];
int n,m,e_num,vis_num,cnt,head[N],instack[N],low[N],tim[N],belong[N];
void AddEdge(int a,int b){
edge[e_num].s=a; edge[e_num].e=b; edge[e_num].next=head[a]; head[a]=e_num++;
}
stack <int>st;
void tarjan(int x){
int i;
tim[x]=low[x]=++vis_num;
instack[x]=1;
st.push(x);
for(i=head[x];i!=-1;i=edge[i].next){
int u=edge[i].e;
if(tim[u]==-1){
tarjan(u);
if(low[x]>low[u])low[x]=low[u];
}
else if(instack[u] && low[x]>tim[u])low[x]=tim[u];
}
if(low[x]==tim[x]){
cnt++;
do{
i=st.top();
st.pop();
instack[i]=0;
belong[i]=cnt;
}while(i!=x);
}
}
void init(){
vis_num=cnt=0;
memset(instack,0,sizeof(instack));
memset(belong,-1,sizeof(belong));
memset(tim,-1,sizeof(tim));
memset(low,0,sizeof(low));
}
int main()
{
int t,i,left,right,mid,ans;
int a[N],b[N],c[N];
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(i=0;i<m;i++)
scanf("%d%d%d",&a[i],&b[i],&c[i]);
left=0; right=m;
while(left<=right){
mid=(left+right)/2;
e_num=0;
memset(head,-1,sizeof(head));
for(i=0;i<mid;i++){
if(c[i]==0){//x[ a[i] ],x[ b[i] ]不能同时为0
AddEdge(2*a[i],2*b[i]+1);
AddEdge(2*b[i],2*a[i]+1);
}
else if(c[i]==1){//x[ a[i] ],x[ b[i] ]不能不同
AddEdge(2*a[i],2*b[i]);
AddEdge(2*a[i]+1,2*b[i]+1);
AddEdge(2*b[i],2*a[i]);
AddEdge(2*b[i]+1,2*a[i]+1);
}
else{//x[ a[i] ],x[ b[i] ]不能同时为1
AddEdge(2*a[i]+1,2*b[i]);
AddEdge(2*b[i]+1,2*a[i]);
}
}
init();
for(i=0;i<2*mid;i++){
if(tim[i]==-1)tarjan(i);
}
int flag=1;
for(i=0;i<mid;i++){
if(belong[2*i]==belong[2*i+1]){
flag=0;break;
}
}
if(flag){
ans=mid; left=mid+1;
}
else right=mid-1;
}
printf("%d\n",ans);
}
return 0;
}