日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

bzoj 4945: [Noi2017]游戏

發布時間:2025/4/9 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 bzoj 4945: [Noi2017]游戏 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Description

Solution

首先我們發現一個位置如果不是 \('x'\),那么就只有兩種選擇
\('x'\) 的個數小于等于 \(8\),直接枚舉是哪個就好了

然后就是 \(2-sat\) 連邊:
設一個點 \(i\) 的對立點為 \(i'\)
如果 \(a[i]=h[i]\),那么就可以直接忽略這個限制
如果 \(a[j]=h[j]\),那么 \(i\) 就不能選 \(a[i]\),為了保證這個限制直接連邊 \((i,i')\) 就好了
如果上述兩種情況都不是,那么直接連 \((i,j),(j',i')\) 就好了

值得注意的是:
\(2-sat\) 如果沒有字典序最小的要求,可以直接 \(tarjan\) \(O(n)\) 的判斷是否合法
方法就是判斷對立點是否在同一強連通分量里即可

輸出方案(拓撲排序貪心):
正向貪心會有后效性
把縮點之后的 \(DAG\) 的邊反向,發現一個點 \(i\) 選了之后,拓撲序在 \(i'\) 之后的點就都不可以選了
每一次選了 \(i\) 之后,就把 \(i'\) 打上標記即可,就不拿有標記的點刪邊了

#include<bits/stdc++.h> using namespace std; const int N=100010; int n,D,m,lis[N],fr[N],tr[N];char s[N],a[N],b[N]; int head[N],nxt[N*2],to[N*2],num=1,in[N]; inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;} int dfn[N],low[N],DFN=0,st[N],top,sum,be[N];bool inst[N],vis[N],fc[N]; vector<int>v[N],sc[N];vector<int>::iterator it; inline void Clear(){num=1;DFN=sum=top=0;for(register int i=0;i<N;i++)vector<int>().swap(sc[i]),head[i]=low[i]=dfn[i]=inst[i]=0; } inline int id(int i,char j){if(s[i]=='a'){if(j=='b')return i;return i+n;}if(s[i]=='b'){if(j=='a')return i;return i+n;}if(j=='a')return i;return i+n; } inline int f(int x){return x>n?x-n:x+n;} inline void tarjan(int x){low[x]=dfn[x]=++DFN;inst[x]=1;st[++top]=x;for(int i=head[x],u;i;i=nxt[i]){if(!dfn[u=to[i]])tarjan(u),low[x]=min(low[x],low[u]);else if(inst[u])low[x]=min(low[x],dfn[u]);}if(low[x]==dfn[x]){int v;sum++;do{v=st[top--];be[v]=sum;inst[v]=0;sc[sum].push_back(v);}while(top && v!=x);} } inline void Cliear(){for(register int i=0;i<N;i++)vector<int>().swap(v[i]),in[i]=vis[i]=fc[i]=0; } inline void solve(){Clear();for(int i=1;i<=m;i++){if(s[fr[i]]==a[i])continue;if(s[tr[i]]==b[i])link(id(fr[i],a[i]),f(id(fr[i],a[i])));else{int x=id(fr[i],a[i]),y=id(tr[i],b[i]);link(x,y);link(f(y),f(x));}}for(int i=1,li=n*2;i<=li;i++)if(!dfn[i])tarjan(i);for(int i=1;i<=n;i++)if(be[i]==be[i+n])return ;Cliear();for(int i=1,li=n*2;i<=li;i++)for(int j=head[i];j;j=nxt[j]){int u=to[j];if(be[u]==be[i])continue;v[be[u]].push_back(be[i]);in[be[i]]++;}queue<int>Q;for(int i=1;i<=sum;i++)if(!in[i])Q.push(i);while(!Q.empty()){int x=Q.front();Q.pop();if(vis[x])continue;fc[x]=1;for(it=sc[x].begin();it!=sc[x].end();++it)vis[be[f(*it)]]=1;for(it=v[x].begin();it!=v[x].end();++it)if(!(--in[*it]))Q.push(*it);}for(int i=1;i<=n;i++){if(fc[be[i]]){if(s[i]=='a')putchar('B');else putchar('A');}else{if(s[i]=='c')putchar('B');else putchar('C');}}exit(0); } inline void dfs(int x){if(x==D+1){solve();return ;}s[lis[x]]='a';dfs(x+1);s[lis[x]]='b';dfs(x+1); } int main(){freopen("pp.in","r",stdin);freopen("pp.out","w",stdout);scanf("%d%d%s",&n,&D,s+1);for(int i=1,j=0;i<=n;i++)if(s[i]=='x')lis[++j]=i;scanf("%d",&m);char p1[2],p2[2];for(int i=1;i<=m;i++){scanf("%d%s%d%s",&fr[i],p1,&tr[i],p2);a[i]=p1[0]+32;b[i]=p2[0]+32;}dfs(1);puts("-1");return 0; }

轉載于:https://www.cnblogs.com/Yuzao/p/8591195.html

總結

以上是生活随笔為你收集整理的bzoj 4945: [Noi2017]游戏的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。