考慮把有種車不適合跑這樣的條件轉化一下
種不適合跑種適合跑,並且只能選一種車去跑
可以看到這就是一個模板了。
考慮一下限制。
對於每場比賽拆成個點,以及,表示這場比賽使用了哪輛適合的車
若圖選擇,圖選擇:
如果不適合在用,直接略過。
反之,如果並不適合在用,那麼就讓向連邊,表示這個方案並不可行。
如果都適合則連邊,。
最後檢測和是否在一個強聯通分量裏即可。
但是有一種圖滿足種車都可以跑,考慮到這種圖非常少( ),暴力枚舉它適合哪兩輛車即可。判定所有方案是否存在可行解即可。
#include <bits/stdc++.h>
int n,d;
int m;
int Time,top;
char s[201000];
int cn[201000];
int dfn[201000];
int low[201000];
int tck[201000];
int vis[201000];
int pos[10],C;
int scc[201000],c;
int head[201000],tot;
struct qwq{
int p1;
char qwp1[1];
int use1;
int p2;
char qwp2[1];
int use2;
}limit[201000];
struct edge{
int to;
int nxt;
}e[201000];
void add(int x,int y){
e[++tot]={y,head[x]};
head[x]=tot;
}
std::pair<int,int> point(int place,int use){
if(cn[place]==1)
return use==2?std::make_pair(place,place+n):std::make_pair(place+n,place);
else
return use==1?std::make_pair(place,place+n):std::make_pair(place+n,place);
}
void make_edge(){
for(int i=1;i<=m;++i){
if(cn[limit[i].p1]==limit[i].use1)
continue;
std::pair<int,int> fst=point(limit[i].p1,limit[i].use1);
if(cn[limit[i].p2]==limit[i].use2){
add(fst.first,fst.second);
continue;
}
std::pair<int,int> scd=point(limit[i].p2,limit[i].use2);
add(fst.first,scd.first);
add(scd.second,fst.second);
}
}
void tarjan(int x){
dfn[x]=low[x]=++Time;
tck[++top]=x;
vis[x]=1;
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].to;
if(!dfn[y]){
tarjan(y);
low[x]=std::min(low[x],low[y]);
}
else
if(vis[y])
low[x]=std::min(low[x],dfn[y]);
}
if(dfn[x]==low[x]){
++c;
while(tck[top]!=x){
vis[tck[top]]=0;
scc[tck[top]]=c;
--top;
}
vis[tck[top]]=0;
scc[tck[top]]=c;
--top;
}
}
main(){
scanf("%d%d",&n,&d);
scanf("%s",s+1);
scanf("%d",&m);
for(int i=1;i<=m;++i){
scanf("%d%s%d%s",&limit[i].p1,limit[i].qwp1,&limit[i].p2,limit[i].qwp2);
limit[i].use1=limit[i].qwp1[0]-'A'+1;
limit[i].use2=limit[i].qwp2[0]-'A'+1;
}
int len=strlen(s+1);
for(int i=1;i<=len;++i){
if(s[i]=='a')
cn[i]=1;
if(s[i]=='b')
cn[i]=2;
if(s[i]=='c')
cn[i]=3;
if(s[i]=='x')
pos[++C]=i;
}
for(int i=0;i<=(1<<d)-1;++i){
tot=c=Time=top=0;
memset(head,0,sizeof head);
memset(dfn,0,sizeof dfn);
memset(low,0,sizeof low);
memset(scc,0,sizeof scc);
memset(tck,0,sizeof tck);
memset(vis,0,sizeof vis);
for(int j=0;j<d;++j)
if(i&(1<<j))
cn[pos[j+1]]=1;
else
cn[pos[j+1]]=2;
make_edge();
for(int j=1;j<=2*n;++j)
if(!dfn[j])
tarjan(j);
int f=0;
for(int j=1;j<=n;++j)
if(scc[j]==scc[j+n])
f=1;
if(!f){
for(int j=1;j<=n;++j){
if(cn[j]==1)
if(scc[j]<scc[j+n])
putchar('B');
else
putchar('C');
if(cn[j]==2)
if(scc[j]<scc[j+n])
putchar('A');
else
putchar('C');
if(cn[j]==3)
if(scc[j]<scc[j+n])
putchar('A');
else
putchar('B');
}
return 0;
}
}
puts("-1");
return 0;
}