Description
有n个人,每个人手里有一把手枪。一开始所有人都选定一个人瞄准(有可能瞄准自己)。然后他们按某个顺序开枪,且任意时刻只有一个人开枪。因此,对于不同的开枪顺序,最后死的人也不同。
Input
输入n人数<1000000 每个人的aim
Solution
其实就是一个基环树森林
显然可以把每个基环树分开,然后分情况讨论。
环:死最多:len-1,死最少:[len/2]上取整
自环:最多最少都是1
树:死最多:只剩下叶子。死最少:叶子不会死,然后父亲一定死,就贪心地让父亲就别打死爷爷。这样一定不会更劣。大概就是隔一层打一层
基环树:死最多:只剩下叶子。死最少:先把每个子树按照树的打法打完,然后基环可能会变成若干个链,每个链都是:len/2下取整。剩环的话,那么和环(或者自环)一样。
树和基环树的叶子往上打就是拓扑排序。
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1000000+5; int n; struct node{ int nxt,to; }e[2*N]; int hd[N],cnt=1; int du[N];//you xiang int huan;//len of huan bool on[N];//on the huan bool vis[N]; bool die[N]; bool go[N]; bool has[N]; int to[N]; int mxans,mians; void add(int x,int y){ e[++cnt].nxt=hd[x]; e[cnt].to=y; hd[x]=cnt; } bool fl; int sta[N],top; vector<int>mem; int in[N];//in the sta void dfs(int x,int in_edge){ // cout<<" dfs "<<x<<" "<<endl; sta[++top]=x; vis[x]=1;in[x]=1; mem.push_back(x); for(int i=hd[x];i;i=e[i].nxt){ int y=e[i].to; if(i==(in_edge^1)) continue; if(vis[y]){ if(in[y]&&!fl){ // cout<<" fin "<<y<<endl; fl=true; int z;//=sta[top]; do{ z=sta[top]; on[z]=1;in[z]=0; huan++; top--; }while(z!=y); } } else dfs(y,i); } if(sta[top]==x) in[x]=0,top--; } int q[N],l,r; int len;//len of lian void wrk(int x,int pre){//dfs on the huan go[x]=1; //cout<<x<<" "<<pre<<endl; for(int i=hd[x];i;i=e[i].nxt){ int y=e[i].to; if(y==pre) continue; if(go[y]) continue; if(on[y]){ //cout<<" y "<<y<<endl; if(die[y]){ mians+=len/2;len=0; }else len++; wrk(y,x); } } } void topo(){ len=0; l=1,r=0; //cout<<" huan "<<huan<<endl; //cout<<" mem "<<mem.size()<<endl; ///cout<<mians<<endl; for(int i=0;i<mem.size();i++){ int id=mem[i]; //cout<<id<<" "<<on[id]<<" "<<in[id]<<endl; if(du[id]==0) q[++r]=id,has[id]=1; } if(huan==0||huan>1) mxans+=mem.size()-max(r,1); else mxans+=mem.size()-r; bool kil=false; int st; while(l<=r){ int x=q[l++]; //cout<<" x "<<x<<endl; //if(has[to[x]]) continue; if(!die[x]){ if(!die[to[x]]) mians++,die[to[x]]=1; if(on[to[x]])kil=1,st=to[x]; } du[to[x]]--; if(du[to[x]]==0){ q[++r]=to[x]; } } if(kil){ //cout<<" kil "<<st<<endl; //cout<<mians<<endl; wrk(st,0); //cout<<" len "<<len<<endl; mians+=len/2; } else{ mians+=huan-(huan/2); } } int main(){ scanf("%d",&n);int y; for(int i=1;i<=n;i++){ scanf("%d",&y);to[i]=y; add(i,y);add(y,i);du[y]++; } for(int i=1;i<=n;i++){ if(!vis[i]){ //cout<<" another "<<i<<endl; fl=false; huan=0; mem.clear(); dfs(i,0); topo(); //cout<<" mians "<<mians<<" mxans "<<mxans<<endl; } } cout<<mians<<" "<<mxans<<endl; return 0; } /* Author: *Miracle* Date: 2018/10/14 19:28:35 */