【圖論】2018國慶三校聯考D5T2
阿新 • • 發佈:2018-11-07
分析:
題意非常醜陋。。。簡化出來就一句話:每個點有選中、未選中兩種狀態,現在給出一些矛盾關係,要求加入儘可能少的矛盾關係,使得沒有合法方案。
如此2sat的模型,顯然需要2sat的連邊方式。。。然後直接列舉每個位置選、不選是否合法即可。若不選合法,則考慮其練的邊是否有一個選擇的點,如果有則可以用1的代價使得這個點不選非法。具體的情況見程式碼:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 4010
using namespace std;
struct node{
int x;
node *nxt;
}edge[MAXN*4];
node *head[MAXN],*ncnt=edge;
int n,m;
void add_edge(int u,int v){
ncnt++;
ncnt->x=v;
ncnt->nxt=head[u];
head[u]=ncnt;
}
bool vis[MAXN];
void dfs(int x){
vis[x]=1;
for (node *v=head[x];v!=NULL;v=v->nxt){
int u=v->x;
if(vis[u]==0)
dfs(u);
}
}
int query(int x){
memset(vis,0,sizeof vis);
dfs(x);
for(int i=1;i<=n;i++)
if(vis[i]==1&&vis[i+n]==1)
return 0;
return 1;
}
int check(){
for(int i=1;i<=n;i++)
if(vis[i]==1)
return 1;
return 0;
}
int l[MAXN];
int main(){
freopen("god.in","r",stdin);
freopen("god.out","w",stdout);
int t;
SF("%d",&t);
while(t--){
SF("%d%d",&n,&m);
for(int i=1;i<=n*2;i++)
head[i]=NULL;
ncnt=edge;
int ans=3,u,v;
for(int i=1;i<=m;i++){
SF("%d%d",&u,&v);
if(u<0)
u=-u+n;
if(v<0)
v=-v+n;
add_edge(u,(v+n)%(2*n));
add_edge(v,(u+n)%(2*n));
}
for(int i=1;i<=n;i++){
int res1=query(i);
int res2=query(i+n);
int con=check();
if(res2==0)
ans=min(ans,res1);
else if(con==1)
ans=min(ans,1+res1);
}
if(ans==3)
PF("No Way\n");
else
PF("%d\n",ans);
}
}