Tarjan 求调
查看原帖
Tarjan 求调
232838
huangkx楼主2022/7/27 09:22

RT,写的是按差分约束的方法建图,然后 Tarjan 缩点、判无解,最后拓扑排序 + DP 求最短路。WA,70 分。谢谢。

#include <bits/stdc++.h>
#define int long long
using namespace std;
namespace IO
{
	inline int read()
	{
		int f = 1, x = 0;
		char c = getchar();
		while(c < '0' || c > '9'){
			if(c == '-') f = -1;
			c = getchar();
		}
		while(c >= '0' && c <= '9'){
			x = x * 10 + c - '0';
			c = getchar();
		}
		return f * x;
	}
	inline void write(int x)
	{
		if(x < 0){
			putchar('-');
			x = -x;
		}
		if(x > 9) write(x / 10);
		putchar(x % 10 + '0');
	}
}
using namespace IO;
void solve();
signed main()
{
	solve();
	return 0;
}
const int MAXN = 1e5;
int n, m;
vector < vector < pair < int, int > > > g(MAXN + 5);
vector < vector < pair < int, int > > > ng(MAXN + 5);
int idx, sum;
int dfn[MAXN + 5], low[MAXN + 5], clr[MAXN + 5];
bool vis[MAXN + 5];
stack < int > s;
int siz[MAXN + 5], indeg[MAXN + 5], f[MAXN + 5];
queue < int > q;
int minn, ans;
void Add(int u, int v, int w)
{
	g[u].push_back(make_pair(v, w));
}
void Tarjan(int u)
{
	s.push(u), vis[u] = true, dfn[u] = low[u] = ++ idx;
	for(auto i : g[u]){
		int v = i.first;
		if(dfn[v] == 0) Tarjan(v), low[u] = min(low[u], low[v]);
		else if(vis[v] == true) low[u] = min(low[u], dfn[v]);
	}
	if(dfn[u] == low[u]){
		sum ++;
		int v; do { v = s.top(), s.pop(), vis[v] = false, clr[v] = sum, siz[sum] ++; } while(u != v);
	}
}
void solve()
{
	freopen("[SCOI 2011] 糖果/P3275_8.in", "r", stdin);
	n = read(), m = read();
	for(int i = 1; i <= m; i ++){
		int t = read(), u = read(), v = read();
		if(t == 1) Add(u, v, 0), Add(v, u, 0);
		if(t == 2) Add(v, u, - 1);
		if(t == 3) Add(u, v, 0);
		if(t == 4) Add(u, v, - 1);
		if(t == 5) Add(v, u, 0);
	}
	for(int u = 1; u <= n; u ++) if(dfn[u] == 0) Tarjan(u);
	for(int u = 1; u <= n; u ++){
		for(auto i : g[u]){
			int v = i.first, w = i.second;
			if(clr[u] == clr[v]){
				if(w == - 1){
					write( - 1), putchar('\n');
					return;
				}else continue;
			}
			ng[clr[u]].push_back(make_pair(clr[v], w));
			indeg[clr[v]] ++;
		}
	}
	for(int u = 1; u <= sum; u ++) f[u] = 2e18;
	for(int u = 1; u <= sum; u ++) if(indeg[u] == 0) q.push(u), f[u] = 0;
	while( ! q.empty()){
		int u = q.front(); q.pop();
		for(auto i : ng[u]){
			int v = i.first, w = i.second;
			f[v] = min(f[v], f[u] + w);
			if( -- indeg[v] == 0) q.push(v);
		}
	}
	minn = 2e18;
	for(int u = 1; u <= sum; u ++) minn = min(minn, f[u]);
	for(int u = 1; u <= sum; u ++) ans += f[u] * siz[u];
	ans -= n * (minn - 1);
	write(ans), putchar('\n');
}
2022/7/27 09:22
加载中...