zoukankan      html  css  js  c++  java
  • 【YBTOJ】【Luogu P3275】[SCOI2011]糖果

    链接:

    洛谷

    题目大意:

    对于 (n) 点,点有点权,从一开始,给你 (m) 个相对关系。求出点权和的最小值。

    (1leq n,mleq 10^5)

    正文:

    转化关系:

    [egin{aligned}a_i=a_j& ightarrow a_jleq a_i,a_ileq a_j\ a_i<a_j& ightarrow a_i< a_j\ a_igeq a_j& ightarrow a_jleq a_i\ a_i>a_j& ightarrow a_j< a_i\ a_ileq a_j& ightarrow a_ileq a_j\end{aligned}]

    然后连边,若两者之间符号是 “(leq)”,边权为零,否则为一。

    最后缩点跑拓扑 DP 就行了。

    代码:

    const int N = 1e5 + 10;
    
    inline ll Read()
    {
    	ll x = 0, f = 1;
    	char c = getchar();
    	while (c != '-' && (c < '0' || c > '9')) c = getchar();
    	if (c == '-') f = -f, c = getchar();
    	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
    	return x * f;
    }
    
    int n, m;
    
    int head[N], tot;
    struct edge
    {
    	int from, to, w, nxt;
    }e[2 * N];
    
    void Add(int u, int v, int w) {e[++tot] = (edge){u, v, w, head[u]}, head[u] = tot;} 
    
    int dfn[N], low[N], col[N], cnt[N], stk[N], top, num, coln;
    
    void Tarjan(int u)
    {
    	low[u] = dfn[u] = ++ num;
    	stk[++top] = u;
    	for (int i = head[u], v; i; i = e[i].nxt)
    		if(!dfn[v = e[i].to])
    		{
    			Tarjan(v);
    			low[u] = min(low[u], low[v]);
    		}else
    			if (!col[v])
    				low[u] = min(low[u], dfn[v]);
    	if (low[u] == dfn[u])
    	{
    		coln++;
    		do
    		{
    			col[stk[top]] = coln;
    			cnt[coln] ++;
    			top--;
    		}while(u != stk[top + 1]);
    	}
    }
    
    ll ind[N], dis[N], ans;
    queue <int> q;
    
    void Topo()
    {
    	for (int i = 1; i <= coln; i++)
    	{
    		dis[i] = 1; 
    		if(!ind[i]) q.push(i);
    	}
    	ans = 0;
    	while (!q.empty())
    	{
    		int u = q.front(); q.pop();
    		ans += dis[u] * cnt[u];
    		for (int v, i = head[u]; i; i = e[i].nxt)
    		{
    			--ind[v = e[i].to];
    			dis[v] = max(dis[v], dis[u] + e[i].w);
    			if (!ind[v]) q.push(v);
    		}
    	}
    }
    
    int main()
    {
    	n = Read(), m = Read();
    	for (int i = 1; i <= m; i++)
    	{
    		int opt = Read(), u = Read(), v = Read();
    		if (opt == 1) Add(u, v, 0), Add(v, u, 0);
    		if (opt == 2) Add(u, v, 1);
    		if (opt == 3) Add(v, u, 0); 
    		if (opt == 4) Add(v, u, 1);
    		if (opt == 5) Add(u, v, 0);
    	}
    	for (int i = 1; i <= n; i++)
    		if (!dfn[i]) Tarjan(i);
    	
    	m = tot, tot = 0;
    	memset (head, 0, sizeof head);
    	for (int i = 1; i <= m; i++)
    		if (col[e[i].from] != col[e[i].to])
    			ind[col[e[i].to]]++, Add(col[e[i].from], col[e[i].to], e[i].w);
    		else if(e[i].w) {puts("-1"); return 0;} 
    	
    	Topo();
    	
    	printf ("%lld", ans);
    	return 0;
    }
    
  • 相关阅读:
    python学习笔记(2)
    数据分析工具pandas
    python学习笔记(1)
    python学习笔记(3)
    python学习笔记(2):科学计算及数据可视化入门
    python学习笔记(1):python基础
    js setTimeout 和 setInterval 区别
    C#根据URL生成签名
    jquery.validate.js客户端验证
    redis学习(一)
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14818352.html
Copyright © 2011-2022 走看看