CF27D Ring Road 2
挺经典的题,是 P3209 [HNOI2010] 平面图判定 的无限弱化版。
考虑连边只会有两种情况,一种是连接的边在环内,一种是连接的边在环外,不妨定义在环内取 ,在环外取 。
如果两条边同时连在环内或者同时在环外有相交的话,这时候就出现矛盾了,很显然,如果其中任意一条边取 的话,那么剩下那条边就必须取 。
这就是一个很经典的 的格式了吧,对于这个我们当然可以考虑用 2-SAT 直接解决。
但是对于这种格式,我们同样可以通过二分图染色的方式进行解决,对于有矛盾的两条边直接对他们的编号连无向边,边的含义就是两端点不能同时颜色相同,钦定开始为 进行二分图染色,如果矛盾则无解。
#include<bits/stdc++.h>
using namespace std;
const int N =1e5+10;
vector<int> g[N<<1];
int n,m,c[N],vis[N],U[N],V[N],cal[N],flag;
bool vis1[N][3];
stack<int> sta;
void Add(int u,int v){
g[u].push_back(v),g[v].push_back(u);
}
void color(int u,int col){
vis[u]=1,c[u]=col;
for(int i=0;i<g[u].size();i++){
int v=g[u][i];
if(c[v]!=0&&c[v]!=-col) flag=false;
if(c[v]==0) color(v,-col);
}
}
int main()
{
flag=true;
cin>>n>>m;
for(int i=1;i<=m;i++) cin>>U[i]>>V[i];
for(int i=1;i<=m;i++) if(U[i]>V[i]) swap(U[i],V[i]);
for(int i=1;i<=m;i++)
for(int j=i+1;j<=m;j++){
if(i==j) continue;
if(U[i]==U[j]||V[i]==V[j]) continue;
if((U[i]<U[j]&&V[i]>U[j]&&V[i]<V[j])||(U[i]>U[j]&&U[i]<V[j]&&V[i]>V[j])) Add(i,j);
}
for(int i=1;i<=2*m-1;i++) if(!vis[i]) color(i,1);
if(flag==false) cout<<"Impossible"<<endl;
else{
for(int i=1;i<=m;i++) cout<<((c[i]==1)?"o":"i");
cout<<endl;
}
return 0;
}

浙公网安备 33010602011771号