• JZOJ 4253.QYQ在艾泽拉斯


    ( ext{Problem})

    有向不联通图,求每个子图至多选出一条最大权值和的路径,求前 (k+1)

    ( ext{Solution})

    显然将每个子图缩点后 (dp),排序 (dp) 值即可
    很多细节要处理

    ( ext{Code})

    #include<cstdio>
    #include<algorithm>
    #define re register
    using namespace std;
    
    const int N = 1e5 + 5, M = 1e6 + 5; 
    int n, m, k, a[N], Q[N], len;
    
    struct edge{
    	int to, nxt;
    }e[M], E[M], _e[M];
    int h[N], H[N], _h[N];
    
    inline void add(int x, int y)
    {
    	static int tot = 0;
    	e[++tot] = edge{y, h[x]}, h[x] = tot;
    }
    inline void Add(int x, int y)
    {
    	static int Tot = 0;
    	E[++Tot] = edge{y, H[x]}, H[x] = Tot;
    }
    inline void _add(int x, int y)
    {
    	static int _tot = 0;
    	_e[++_tot] = edge{y, _h[x]}, _h[x] = _tot;
    }
    
    int bz[N];
    void find(int x)
    {
    	Q[++len] = x, bz[x] = 1;
    	for(re int i = H[x]; i; i = E[i].nxt)
    	{
    		int v = E[i].to;
    		if (bz[v]) continue;
    	 	find(v);
    	}
    }
    
    int dfn[N], low[N], vis[N], st[N], top, dfc, col[N], color;
    void tarjan(int x)
    {
    	st[++top] = x, dfn[x] = low[x] = ++dfc, vis[x] = 1;
    	for(re int i = h[x]; i; i = e[i].nxt)
    	{
    		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], dfn[v]);
    	}
    	if (low[x] == dfn[x])
    	{
    		col[x] = ++color, vis[x] = 0;
    		while (st[top] != x) col[st[top]] = color, vis[st[top]] = 0, --top;
    		--top;
    	}
    }
    
    int _Q[N], f[N], g[N], cnt, in[N], _in[N], cur, val[N];
    inline void topu() 
    {
    	for(re int i = 1; i <= len; i++)
    	{
    		val[col[Q[i]]] += a[Q[i]];
    		for(re int j = h[Q[i]]; j; j = e[j].nxt)
    			if (col[e[j].to] != col[Q[i]]) _add(col[Q[i]], col[e[j].to]);
    	} 
    	for(re int i = cur + 1; i <= color; i++)
    		for(re int j = _h[i]; j; j = _e[j].nxt) _in[_e[j].to]++;
    		
    	int head = 0, tail = 0;
    	for(re int i = cur + 1; i <= color; i++)
    	{
    		f[i] = val[i];
    		if (!_in[i]) _Q[++tail] = i;
    	}
    	while (head < tail)
    	{
    		int now = _Q[++head];
    		for(re int i = _h[now]; i; i = _e[i].nxt)
    		{
    			f[_e[i].to] = max(f[_e[i].to], f[now] + val[_e[i].to]), --_in[_e[i].to];
    			if (!_in[_e[i].to]) _Q[++tail] = _e[i].to;
    		}
    	}
    	++cnt;
    	for(re int i = cur + 1; i <= color; i++) g[cnt] = max(g[cnt], f[i]);
    	cur = color;
    }
    
    int main()
    {
    	freopen("azeroth.in", "r", stdin);
    	freopen("azeroth.out", "w", stdout);
    	scanf("%d%d", &n, &m);
    	for(re int i = 1, u, v; i <= m; i++)
    	{
    		scanf("%d%d", &u, &v);
    		if (u ^ v) add(u, v), Add(u, v), Add(v, u);
    	} 
    	for(re int i = 1; i <= n; i++) scanf("%d", &a[i]);
    	scanf("%d", &k);
    	for(re int i = 1; i <= n; i++)
    	if (!bz[i])
    	{
    		len = top = 0, find(i);
    		for(re int j = 1; j <= len; j++)
    		if (!dfn[Q[j]]) tarjan(Q[j]);
    		topu();
    	}
    	sort(g + 1, g + cnt + 1), ++k; 
    	int ans = 0;
    	for(re int i = cnt; i && k; --i, --k) ans += g[i];
    	printf("%d
    ", ans);
    }
    
  • 相关阅读:
    FreeModbus TCP
    C#之用户自定义控件
    使用C库制作DLL
    C# Unable to load DLL 'WzCanDll.dll':找不到指定的模块
    C#之改变窗体icon图标、新建类文件、调用dll库
    sim800c GPRS模块的透传模式
    STM32上使用JSON
    STM32之串口IAP更新升级
    Fortran语言的REWIND和BACKSPACE 函数
    Code blocks 编译Fortran(转载)
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/15125991.html
Copyright © 2020-2023  润新知