Forwarding Emails
Time Limit: 1000ms
Memory Limit: 131072KB
This problem will be judged on UVA. Original ID: 12442
64-bit integer IO format: %lld Java class name: Main
Submit Status Statistics Discuss
Type:
None
None
Graph Theory
2-SAT
Articulation/Bridge/Biconnected Component
Cycles/Topological Sorting/Strongly Connected Component
Shortest Path
Bellman Ford
Dijkstra/Floyd Warshall
Euler Trail/Circuit
Heavy-Light Decomposition
Minimum Spanning Tree
Stable Marriage Problem
Trees
Directed Minimum Spanning Tree
Flow/Matching
Graph Matching
Bipartite Matching
Hopcroft–Karp Bipartite Matching
Weighted Bipartite Matching/Hungarian Algorithm
Flow
Max Flow/Min Cut
Min Cost Max Flow
DFS-like
Backtracking with Pruning/Branch and Bound
Basic Recursion
IDA* Search
Parsing/Grammar
Breadth First Search/Depth First Search
Advanced Search Techniques
Binary Search/Bisection
Ternary Search
Geometry
Basic Geometry
Computational Geometry
Convex Hull
Pick‘s Theorem
Game Theory
Green Hackenbush/Colon Principle/Fusion Principle
Nim
Sprague-Grundy Number
Matrix
Gaussian Elimination
Matrix Exponentiation
Data Structures
Basic Data Structures
Binary Indexed Tree
Binary Search Tree
Hashing
Orthogonal Range Search
Range Minimum Query/Lowest Common Ancestor
Segment Tree/Interval Tree
Trie Tree
Sorting
Disjoint Set
String
Aho Corasick
Knuth-Morris-Pratt
Suffix Array/Suffix Tree
Math
Basic Math
Big Integer Arithmetic
Number Theory
Chinese Remainder Theorem
Extended Euclid
Inclusion/Exclusion
Modular Arithmetic
Combinatorics
Group Theory/Burnside‘s lemma
Counting
Probability/Expected Value
Others
Tricky
Hardest
Unusual
Brute Force
Implementation
Constructive Algorithms
Two Pointer
Bitmask
Beginner
Discrete Logarithm/Shank‘s Baby-step Giant-step Algorithm
Greedy
Divide and Conquer
Dynamic Programming
Tag it!
J |
Forwarding Emails |
"... so forward this to ten other people, to prove that you believe the emperor has new clothes."
Aren‘t those sorts of emails annoying?
Martians get those sorts of emails too, but they have an innovative way of dealing with them. Instead of just forwarding them willy-nilly, or not at all, they each pick one other person they know to email those things to every time - exactly one, no less, no more (and never themselves). Now, the Martian clan chieftain wants to get an email to start going around, but he stubbornly only wants to send one email. Being the chieftain, he managed to find out who forwards emails to whom, and he wants to know: which Martian should he send it to maximize the number of Martians that see it?
Input
The first line of input will contain T (≤ 20) denoting the number of cases.
Each case starts with a line containing an integer N (2 ≤ N ≤ 50000) denoting the number of Martians in the community. Each of the next N lines contains two integers: u v (1 ≤ u, v ≤ N, u ≠ v) meaning that Martian u forwards email to Martian v.
Output
For each case, print the case number and an integer m, where m is the Martian that the chieftain should send the initial email to. If there is more than one correct answer, output the smallest number.
Sample Input |
Output for Sample Input |
3 3 1 2 2 3 3 1 4 1 2 2 1 4 3 3 2 5 1 2 2 1 5 3 3 4 4 5 |
Case 1: 1 Case 2: 4 Case 3: 3 |
题目大意:现在要转发邮件,有n个人,有n条边,表示u--->v可以转发邮件。有一个人想要在这n个人中选一个人作为起点进行邮件转发。想要让转发给的人尽量多,问从哪里开始转发可以满足条件。
解题思路:想转发给的人尽量多,即要求让经过的点尽量多。我们可以在有向图上进行强连通缩点。然后在缩点形成的DAG上进行DFS。然后遍历判断从哪个连通块出发能经过最多的点,在求出该连通块的最小顶点编号即为结果。
#include<bits/stdc++.h> using namespace std; #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) const int maxn=50050; vector<int>G[maxn]; int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt; int dp[maxn],d[maxn]; stack<int>S; set<int>ST[maxn];//新的DAG需要去重边 //tarjan 模板 void dfs(int u){ pre[u]=lowlink[u]=++dfs_clock; S.push(u); for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(!pre[v]){ dfs(v); lowlink[u]=min(lowlink[u],lowlink[v]); }else if(!sccno[v]){ lowlink[u]=min(lowlink[u],pre[v]); } } if(lowlink[u]==pre[u]){ scc_cnt++; for(;;){ int x=S.top();S.pop(); sccno[x]=scc_cnt; if(x==u) break; } } } void find_scc(int n){ dfs_clock=scc_cnt=0; while(!S.empty()) S.pop(); memset(sccno,0,sizeof(sccno)); memset(pre,0,sizeof(pre)); for(int i=0;i<n;i++){ if(!pre[i]) dfs(i); } } int DFS(int u){ if(dp[u]) return dp[u]; dp[u]=d[u]; for(set<int>::iterator it=ST[u].begin();it!=ST[u].end();it++){ int v=*it; if(!dp[v]){ dp[u]+=DFS(v); }else { dp[u]+=dp[v]; } } return dp[u]; } int main(){ int t,n,a,b,cnt=0; scanf("%d",&t); while(t--){ memset(dp,0,sizeof(dp)); memset(d,0,sizeof(d)); scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d%d",&a,&b); a--,b--; G[a].push_back(b); } find_scc(n); for(int i=0;i<n;i++){ d[sccno[i]]++; } for(int i=0;i<n;i++){ for(int j=0;j<G[i].size();j++){ int v=G[i][j]; if(sccno[i]!=sccno[v])//SB了,开始忘了加这个条件,要是不同的连通块 ST[sccno[i]].insert(sccno[v]); } } for(int i=1;i<=scc_cnt;i++){//在连通块形成的DAG上记忆化搜索 if(!dp[i]){ DFS(i); } } int sum=0,ck=0; for(int i=1;i<=scc_cnt;i++){ if(dp[i]>sum){ ck=i; sum=dp[i]; } } int ok=0; for(int i=0;i<n;i++){ if(sccno[i]==ck){ ok=i; break; } } printf("Case %d: %d\n",++cnt,ok+1); for(int i=0;i<=n;i++) G[i].clear(); for(int i=1;i<=scc_cnt;i++){ ST[i].clear(); } } return 0; } /* 55 4 1 2 2 1 4 3 3 2 5 1 2 2 1 5 3 3 4 4 5 */