标签:
Time Limit: 15000MS | Memory Limit: 65536K | |
Total Submissions: 8311 | Accepted: 3017 | |
Case Time Limit: 2000MS |
Description
Input
Output
Sample Input
4 2 1 2 2 1 2 2 2 3 2 3 4 1 2 3 4
Sample Output
2 1 2 2 1 2 1 3 1 4
题意:一个国王有N个王子。一共有N个女孩,每个王子可以喜欢多个女孩,但只能取一个女孩。给定一个参考结婚列表,问每个王子可分别与哪几个女孩结婚。
思路:王子与女孩之间建立有向图,再根据参考结婚列表建立反向边,那么与王子处于同一个连通分量的女孩且是王子喜欢的可以和王子结婚。
附输入输出挂
#include"cstdio" #include"cstring" #include"algorithm" using namespace std; const int MAXN=4010; struct Edge{ int to,next; }es[210000]; int V; void Scan(int &val) { char ch; int x=0; bool flag=true; ch=getchar(); if(ch==‘-‘) flag=false; else if(‘0‘<=ch&&ch<=‘9‘) x=(ch-‘0‘); while((ch=getchar())&&‘0‘<=ch&&ch<=‘9‘) x=x*10+ch-‘0‘; val=(flag==true)?x:-x; } void Print(int x) { if(x>9) Print(x/10); putchar(x%10+‘0‘); } int head[MAXN],tot; void add_edge(int u,int v) { es[tot].to=v; es[tot].next=head[u]; head[u]=tot++; } int index; int dfn[MAXN],low[MAXN]; int stack[MAXN],top; int cpnt[MAXN],cnt; bool instack[MAXN]; void tarjan(int u) { instack[u]=true; stack[top++]=u; dfn[u]=low[u]=++index; for(int i=head[u];i!=-1;i=es[i].next) { int v=es[i].to; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(instack[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { int v; cnt++; do{ v=stack[--top]; instack[v]=false; cpnt[v]=cnt; }while(u!=v); } } int ans[MAXN]; void solve() { memset(ans,0,sizeof(ans)); for(int i=1;i<=V+V;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=V;i++) { int counter=0; for(int j=head[i];j!=-1;j=es[j].next) { int v=es[j].to; if(cpnt[v]==cpnt[i]) ans[counter++]=v-V; } sort(ans,ans+counter); Print(counter); for(int j=0;j<counter;j++) putchar(‘ ‘),Print(ans[j]); putchar(‘\n‘); } } int main() { while(scanf("%d",&V)!=EOF) { tot=index=top=cnt=0; memset(head,-1,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(instack,false,sizeof(instack)); memset(cpnt,0,sizeof(cpnt)); for(int i=1;i<=V;i++) { int k; Scan(k); while(k--) { int v; Scan(v); add_edge(i,V+v); } } for(int i=1;i<=V;i++) { int v; Scan(v); add_edge(V+v,i); } solve(); } return 0; }
kosaraju算法——有向图缩点利器
#include"cstdio" #include"cstring" #include"algorithm" #include"vector" using namespace std; const int MAXN=4010; vector<int> G[MAXN]; vector<int> rG[MAXN]; vector<int> vs; int V,E; void add_edge(int u,int v) { G[u].push_back(v); rG[v].push_back(u); } int vis[MAXN]; int cpnt[MAXN]; void dfs(int u) { vis[u]=1; for(int i=0;i<G[u].size();i++) if(!vis[G[u][i]]) dfs(G[u][i]); vs.push_back(u); } void rdfs(int u,int k) { vis[u]=1; cpnt[u]=k; for(int i=0;i<rG[u].size();i++) if(!vis[rG[u][i]]) rdfs(rG[u][i],k); } void scc() { vs.clear(); memset(vis,0,sizeof(vis)); for(int i=1;i<=V+V;i++) if(!vis[i]) dfs(i); memset(vis,0,sizeof(vis)); int k=1; for(int i=vs.size()-1;i>=0;i--) if(!vis[vs[i]]) rdfs(vs[i],k++); } int ans[MAXN]; void solve() { memset(ans,0,sizeof(ans)); scc(); for(int i=1;i<=V;i++) { int counter=0; for(int j=0;j<G[i].size();j++) { int v=G[i][j]; if(cpnt[i]==cpnt[v]) ans[counter++]=v-V; } sort(ans,ans+counter); printf("%d",counter); for(int i=0;i<counter;i++) printf(" %d",ans[i]); printf("\n"); } } int main() { while(scanf("%d",&V)!=EOF) { for(int i=1;i<=V+V;i++) { G[i].clear(); rG[i].clear(); } for(int i=1;i<=V;i++) { int k; scanf("%d",&k); while(k--) { int v; scanf("%d",&v); add_edge(i,v+V); } } for(int i=1;i<=V;i++) { int v; scanf("%d",&v); add_edge(v+V,i); } solve(); } return 0; }
标签:
原文地址:http://www.cnblogs.com/program-ccc/p/5182520.html