首页 > 代码库 > hdu 3639 有向图缩点+建反向图+搜索
hdu 3639 有向图缩点+建反向图+搜索
题意:给个有向图,每个人可以投票(可以投很多人,一次一票),但是一个人只能支持一人一次,支持可以传递,自己支持自己不算,被投支持最多的人。
开始想到缩点,然后搜索,问题是有一点想错了!以为支持按票数计算,而不是按人数!还各种树形dp/搜索求可以到达边数。。提交WA了。。。
又反复读了题目之后才发现。。错误。。只要人数就行。。。问题简单了许多。。。
缩点成有向无环图后:每个SCC中支持的人数就是scc里面的人,要求可到达的点最多的点,当然要放过来求方便:反向图那个点可以到达的点最多!于是建反向图直接dfs即可,记录答案有点麻烦。。。提交就A了。。。这题总体花了我2多个小时。。算失败。。。
#include<iostream> #include<stack> #include<queue> #include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int inf=0x3f3f3f3f; const int maxv=5005,maxe=50005; int nume=0;int head[maxv];int e[maxe][3]; void inline adde(int i,int j,int c) { e[nume][0]=j;e[nume][1]=head[i];head[i]=nume; e[nume++][2]=c; } int dfn[maxv];int low[maxv];int vis[maxv];int ins[maxv]; stack<int>sta; int scc[maxv];int numb=0;int times=0; int n,m; int sccsize[maxv]; void tarjan(int u) { dfn[u]=low[u]=times++; ins[u]=1; sta.push(u); for(int i=head[u];i!=-1;i=e[i][1]) { int v=e[i][0]; if(!vis[v]) { vis[v]=1; tarjan(v); if(low[v]<low[u])low[u]=low[v]; } else if(ins[v]&&dfn[v]<low[u]) { low[u]=dfn[v]; } } if(low[u]==dfn[u]) { numb++;int counted=0; int cur; do { cur=sta.top(); sta.pop(); ins[cur]=0; scc[cur]=numb; counted++; }while(cur!=u); sccsize[numb]=counted; } } struct pi { int id; int w; }; bool my (pi a,pi b) { if(a.w!=b.w) return a.w>b.w; else return a.id<b.id; } int sums=0; vector<vector<int> >e2(maxv+1); int ind[maxv]; void dfs(int u) { for(int i=0;i<e2[u].size();i++) { int v=e2[u][i]; if(!vis[v]) { vis[v]=1; sums+=sccsize[v]; dfs(v); } } } vector<int>sumss; void solve() { for(int i=0;i<n;i++) { if(!vis[i]) { vis[i]=1; tarjan(i); } } for(int i=0;i<n;i++) for(int j=head[i];j!=-1;j=e[j][1]) { int v=e[j][0]; if(scc[i]!=scc[v]) { e2[scc[v]].push_back(scc[i]); ind[scc[i]]++; } } int minsums=0; vector<pi>ans; for(int i=1;i<=numb;i++) { sums=0; memset(vis,0,sizeof(vis)); if(ind[i]==0) { vis[i]=1; sums+=sccsize[i]-1; dfs(i); if(sums>=minsums) { pi tp; tp.w=sums; tp.id=i; ans.push_back(tp); minsums=sums; } } } vector<int>realans; for(int i=0;i<ans.size();i++) { if(ans[i].w==minsums) { realans.push_back(ans[i].id); } } for(int j=0;j<realans.size();j++) for(int i=0;i<n;i++) { if(scc[i]==realans[j]) { sumss.push_back(i); } } sort(sumss.begin(),sumss.end()); printf("%d\n",minsums); for(int i=0;i<sumss.size();i++) { if(i!=sumss.size()-1) printf("%d ",sumss[i]); else printf("%d\n",sumss[i]); } } void read_build() { int aa,bb,cc; for(int i=0;i<m;i++) { scanf("%d%d",&aa,&bb); adde(aa,bb,0); } } void init() { numb=times=nume=0; sumss.clear(); for(int i=0;i<maxv;i++) { head[i]=-1; ins[i]=dfn[i]=low[i]=scc[i]=vis[i]=0; sccsize[i]=0; ind[i]=0; e2[i].clear(); } } int main() { int T; scanf("%d",&T); int ct=1; while(T--) { scanf("%d%d",&n,&m); init(); read_build(); printf("Case %d: ",ct++); solve(); } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。