【2-sat】Gym - 101201F - Illumination
题意:平面上l盏灯,每盏灯可以照亮横向的2*r+1个格子或者纵向的2*r+1个格子,让你确定每盏灯的方向,使得每个格子只被同一行的不超过一盏灯照亮,并且只被同一列的不超过一盏灯照亮。输出是否有解。
显然的2-sat模型。
#include<cstdio> #include<cstring> #include<vector> using namespace std; vector<int>G[2005],rG[2005],vs; int a[1005][1005]; int n,r,l,xs[1005],ys[1005]; void AddEdge(int U,int V){ G[U].push_back(V); rG[V].push_back(U); } bool used[2005]; void dfs(int U){ used[U]=1; for(int i=0;i<G[U].size();++i){ if(!used[G[U][i]]){ dfs(G[U][i]); } } vs.push_back(U); } int K,cmp[2005]; void rdfs(int U){ used[U]=1; cmp[U]=K; for(int i=0;i<rG[U].size();++i){ if(!used[rG[U][i]]){ rdfs(rG[U][i]); } } } int main(){ // freopen("f.in","r",stdin); scanf("%d%d%d",&n,&r,&l); for(int i=1;i<=l;++i){ scanf("%d%d",&xs[i],&ys[i]); a[xs[i]][ys[i]]=i; } for(int i=1;i<=l;++i){ for(int j=1;j<=2*r && xs[i]+j<=n;++j){ if(a[xs[i]+j][ys[i]]){ AddEdge(i,a[xs[i]+j][ys[i]]+l); } } for(int j=1;j<=2*r && xs[i]-j>=1;++j){ if(a[xs[i]-j][ys[i]]){ AddEdge(i,a[xs[i]-j][ys[i]]+l); } } for(int j=1;j<=2*r && ys[i]+j<=n;++j){ if(a[xs[i]][ys[i]+j]){ AddEdge(i+l,a[xs[i]][ys[i]+j]); } } for(int j=1;j<=2*r && ys[i]-j>=1;++j){ if(a[xs[i]][ys[i]-j]){ AddEdge(i+l,a[xs[i]][ys[i]-j]); } } } for(int i=1;i<=2*l;++i){ if(!used[i]){ dfs(i); } } memset(used,0,sizeof(used)); for(int i=vs.size()-1;i>=0;--i){ if(!used[vs[i]]){ ++K; rdfs(vs[i]); } } for(int i=1;i<=l;++i){ if(cmp[i]==cmp[i+l]){ puts("NO"); return 0; } } puts("YES"); return 0; }
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/