【博弈論】The Showdown
阿新 • • 發佈:2019-03-02
兩個人 最大化 deep main 人在 有一個 win 思維 true
有一個無向圖,邊分為紅邊和藍邊,兩種邊分別構成一棵樹。兩個人在兩棵樹上各一個點。
兩人輪流移動,操作只有兩個:走或不走。你只能走到與所在點相連的點上。
先手在紅樹上移動,後手在藍樹上移動。如果任意時刻兩個人位於同一個點即可輸出
紅樹需要最大化玩家的操作次數,藍樹需要最小化玩家的操作次數。求最終操作次數的值
建樹,先建藍樹
對於一條紅邊\(xy\),若在藍樹上x到y路徑長\(>2\),且先手走到該邊端點時兩人仍未相遇,則只能輸出\(-1\)
把長度大於\(2\)的邊刪掉(稱為“長邊”)
很明顯,走短邊不可能走出藍子樹
因此先手走到一個能走到的深度最大的點之後等後手即可
#include<bits/stdc++.h> #define MAXN 200005 using namespace std; int n,cnt,last[MAXN]; int father[MAXN],deep[MAXN],dis[MAXN]; int q[MAXN],nnn[MAXN],mx[MAXN]; int tim,a[MAXN][2],xx,yy; bool vis[MAXN],win[MAXN]; struct edge { int to,next,h; }t[MAXN*4]; void add(int u,int v,int h) { t[++cnt].to=v;t[cnt].h=h; t[cnt].next=last[u];last[u]=cnt; t[++cnt].to=u;t[cnt].h=h; t[cnt].next=last[v];last[v]=cnt; } void dfs(int x) { deep[x]=deep[father[x]]+1;nnn[x]=++tim; for (int i=last[x];i;i=t[i].next) if (t[i].to!=father[x]) father[t[i].to]=x,dfs(t[i].to); mx[x]=++tim; } bool check(int x,int y) { if (nnn[x]>nnn[y]) swap(x,y); if (nnn[x]<nnn[y]&&mx[x]>nnn[y]) return deep[y]-deep[x]>2 ? true : false; if (father[x]==father[y]) return false; return true; } void bfs() { int h=1,tt=1;q[1]=xx;vis[xx]=1; while (h<=tt) { int x=q[h++]; for (int i=last[x];i;i=t[i].next) if (!t[i].h&&!vis[t[i].to]) { dis[t[i].to]=dis[x]+1; if (dis[t[i].to]<deep[t[i].to]) vis[t[i].to]=1,q[++tt]=t[i].to; } } } int max(int a,int b){return a<b?a:b;}// template<class T>inline void read(T &res) { static char ch;T flag=1; while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48; while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=flag; } int main() { int ans=0; read(n);read(xx);read(yy); for (int i=1;i<n;i++) {read(a[i][0]);read(a[i][1]);} for (int i=1;i<n;i++) { int x,y; read(x);read(y); add(x,y,1); } deep[0]=-1; dfs( yy ); for (int i=1;i<n;i++) { if (check(a[i][0],a[i][1])) win[a[i][0]]=win[a[i][1]]=1; else add(a[i][0],a[i][1],0); } bfs(); for (int i=1;i<=n;i++) if (win[i]&&vis[i]) {putchar('-');putchar('1');return 0;} for (int i=1;i<=n;i++) if (vis[i]) ans=max(ans,deep[i]<<1); printf("%d\n",ans); return 0; }
這題貪心比較好想,博弈策略一定要認真思考(我也是借鑒了\(dalao\)的思路才做出來的)
代碼看一會兒就好了,代碼裏有一個很明顯的錯誤防無腦抄
思維難度比代碼難度大
【博弈論】The Showdown