zoukankan      html  css  js  c++  java
  • 【luogu P1262 间谍网络】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1262
    注意:
    1.缩点时计算出入度是在缩完点的图上用color计算。不要在原来的点上计算。
    2.枚举出入度时是在缩完点的图上计算。枚举范围到num。

    #include <stack>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn = 10000 + 10;
    struct edge{
    	int from, next, to, len;
    }e[maxn<<2];
    int head[maxn], cnt;
    int dfn[maxn], low[maxn], tim, color[maxn], num, rudu[maxn];
    stack<int> s;
    bool vis[maxn], okbuy[maxn], flag[maxn];
    int n, p, m, money[maxn], minpay[maxn], ans;
    void add(int u, int v)
    {
    	e[++cnt].from = u;
    	e[cnt].next = head[u];
    	e[cnt].to = v;
    	head[u] = cnt;
    }
    void tarjan(int x)
    {
    	dfn[x] = low[x] = ++tim;
    	s.push(x); vis[x] = 1;
    	for(int i = head[x]; i != -1; i = e[i].next)
    	{
    		int v = e[i].to;
    		if(!dfn[v])
    		{
    			tarjan(v);
    			low[x] = min(low[x], low[v]);
    		}
    		else if(vis[v])
    		{
    			low[x] = min(low[x], low[v]);
    		}
    	}
    	if(low[x] == dfn[x])
    	{
    		color[x] = ++num;
    		vis[x] = 0;
    		minpay[num] = min(minpay[num], money[x]);
    		while(s.top() != x)
    		{
    			color[s.top()] = num;
    			vis[s.top()] = 0;
    			minpay[num] = min(minpay[num], money[s.top()]);
    			s.pop();
    		}
    		s.pop();
    	}
    }
    int main()
    {
    	memset(head, -1, sizeof(head));
    	scanf("%d%d",&n,&p);
    	for(int i = 1; i <= n; i++) minpay[i] = 0x7fffffff, money[i] = 0x7fffffff;
    	for(int i = 1; i <= p; i++)
    	{
    		int u, val;
    		scanf("%d%d",&u,&val);
    		okbuy[u] = 1;
    		money[u] = val;
    	}
    	scanf("%d",&m);
    	for(int i = 1; i <= m; i++)
    	{
    		int u, v;
    		scanf("%d%d",&u,&v);
    		add(u,v);
    	}
    	for(int i = 1; i <= n; i++)
    		if(!dfn[i] && okbuy[i] == 1) tarjan(i);
    	for(int i = 1; i <= n; i++)
    		if(!dfn[i])
    		{
    			printf("NO
    %d",i);
    			return 0;
    		}
    	for(int i = 1; i <= n; i++)
    		for(int j = head[i]; j != -1; j = e[j].next)
    		{
    			int v = e[j].to;
    			if(color[v] != color[i])
    			{
    				rudu[color[v]]++;
    			}
    		}	
    	for(int i = 1; i <= num; i++)
    	{
    		if(rudu[i] == 0)
    		ans += minpay[i];
    	}
    	printf("YES
    %d
    ",ans);
    	return 0;	
    }
    
  • 相关阅读:
    hdu 3342 Legal or Not 拓排序
    hdu 1596 find the safest road Dijkstra
    hdu 1874 畅通工程续 Dijkstra
    poj 2676 sudoku dfs
    poj 2251 BFS
    poj Prime Path BFS
    poj 3278 BFS
    poj 2387 Dijkstra 模板
    poj 3083 DFS 和BFS
    poj 1062 昂贵的聘礼 dijkstra
  • 原文地址:https://www.cnblogs.com/MisakaAzusa/p/9374501.html
Copyright © 2011-2022 走看看