计蒜客 | 拓扑排序 | 虎威山上的分配

每年过年的时候,座山雕都会给兄弟们分银子,分银子之前,座山雕允许大伙儿发表意见,因为要是没法满足所有人的意见,指不定谁要搞出什么大新闻。不过每个人在提意见的时候只能说:“我认为 A 分的银子应该比 B 多!”。座山雕决定要找出一种分配方案,满足所有人的意见,同时使得所有人分得的银子总数最少,并且每个人分得的银子最少为 100 两。

输入格式

第一行两个整数 n,m(0<n10000,0<m20000),表示总人数和总意见数;

以下 m 行,每行两个整数 a,b,之间用一个空格隔开,表示某个意见认为第 a 号小弟所分得的银两应该比第 b号小弟多,所有小弟的编号由 1开始。

输出格式

若无法找到合法方案,则输出Unhappy!(不包含引号),否则输出一个数表示最少总银两数。

样例输入

3 2
1 2
2 3

样例输出

303


 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int max_num = 100005;
 4 /*
 5     ip:第几条边
 6     indeg:表示入度
 7     seg: 
 8 */
 9 int head[max_num],ip,indegree[max_num];
10 int n,m,seq[max_num];
11 
12 struct note{
13     int v,next;
14 }edge[max_num];
15 
16 void init()
17 {
18     memset(head,-1,sizeof(head));
19     memset(indegree,0,sizeof(indegree)); 
20     ip = 0;    
21 }
22 
23 void addedge(int u,int v) //增加边,u是起点,V是终点 
24 {
25     edge[ip].v = v,edge[ip].next = head[u],head[u] = ip++;
26 }
27 
28 int topo()
29 {
30     int ans = 0;
31     queue<int>q;
32     queue<int>money;  //模板的基础上添加一个存储银子的队列 
33     int indeg[max_num];
34     for(int i = 1; i <= n; i++)
35     {
36         indeg[i] = indegree[i];
37         if(indeg[i] == 0)
38         {
39             q.push(i);
40             money.push(100);  //对于入度为0的人,基础银子为100 
41         }    
42             
43          
44     }    
45     int k = 0;
46     bool res = false;
47     while(!q.empty())
48     {
49         if(q.size() != 1)
50             res = true;
51         int u = q.front();
52         int temp = money.front();
53         ans += temp;
54         q.pop();
55         money.pop();
56         k++;
57         for(int i = head[u]; i != -1; i = edge[i].next)
58         {
59             int v = edge[i].v;
60             indeg[v]--;
61             if(indeg[v] == 0)  //此时这个人不需要比其他人的银子多了 
62             {
63                 q.push(v);
64                 money.push(temp+1);  //依题意,银子总数最少  
65             }
66         }
67     }
68 //    if(k < n)return -1; //存在有向环,总之不能进行拓扑排序 
69 //    if(res) return 0; //可以进行拓扑排序,并且只有唯一一种方式,seq数组即是排序完好的序列 
70 //    return 1; ////可以进行拓扑排序,有多种情况,seq数组是其中一种序列 
71     if(k < n) printf("Unhappy!\n");
72     else printf("%d\n",ans);
73     
74     return 0;
75 }
76 int main()
77 {
78     int a,b;
79     while(~scanf("%d %d",&n,&m))
80     {
81         init();
82         for(int i = 1; i<= m; i++)
83         {
84             scanf("%d %d",&a,&b);
85             addedge(b,a);
86             indegree[a]++;//入度越多 说明分的钱越多 
87         }
88         topo();    
89     }
90     return 0;
91 }

 

posted @ 2017-11-04 15:21  听说这是最长的名字了  阅读(354)  评论(0编辑  收藏  举报