2020牛客暑期多校训练营(第二场) I题题解

题目链接

Interval

题解

将每个区间看做二维平面上的点,我们的目标就是阻止从\((1,n)\)走到任意一个\((x,x)\)
显然相邻的点可以连边,我们把\((1,n)\)看做源点的话,新建一个汇点将所有\((x,x)\)连向汇点,那么这就是一个最小割问题
但是会T。
发现这是一个平面图,转化为对偶图的最短路即可

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define cls(s,v) memset(s,v,sizeof(s))
#define mp(a,b) make_pair<int,int>(a,b)
#define cp pair<int,int>
using namespace std;
const int maxn = 250005,maxm = 100005;
const LL INF = 1000000000000000000ll;
inline int read(){
	int out = 0,flag = 1; char c = getchar();
	while (c < 48 || c > 57){if (c == '-') flag = 0; c = getchar();}
	while (c >= 48 && c <= 57){out = (out << 1) + (out << 3) + c - 48; c = getchar();}
	return flag ? out : -out;
}
int h[maxn],ne;
struct EDGE{
	int to,w,nxt;
}ed[maxn * 2];
void build(int u,int v,int w){
	ed[++ne] = (EDGE){v,w,h[u]}; h[u] = ne;
	ed[++ne] = (EDGE){u,w,h[v]}; h[v] = ne;
	//printf("build %d to %d costs %d\n",u,v,w);
}
int C[505][505],R[505][505];
int n,m,S,T;
int id(int x,int y){
	return x * (x - 1) / 2 + y;
}
LL d[maxn],vis[maxn]; 
struct node{int u; LL d;};
inline bool operator <(const node& a,const node& b){return a.d > b.d;}
priority_queue<node> q;
void dijkstra(){
	for (int i = 1; i <= T; i++) d[i] = INF,vis[i] = false;
	d[S] = 0;
	node u;
	q.push((node){S,d[S]});
	while (!q.empty()){
		u = q.top(); q.pop();
		if (vis[u.u]) continue;
		vis[u.u] = true;
		Redge(u.u) if (!vis[to = ed[k].to] && d[to] > d[u.u] + ed[k].w){
			d[to] = d[u.u] + ed[k].w;
			q.push((node){to,d[to]});
		}
	}
}
int main(){
	n = read(); m = read();
	int l,r,w; char c;
	for (int i = 1; i <= m; i++){
		l = read(); r = read(); scanf("%c",&c); w = read();
		if (c == 'L') R[l][r] = w;
		else C[l][r] = w;
	}
	for (int i = 1; i <= n - 1; i++)
		for (int j = 1; j <= i; j++){
			//puts("LXT");
			//printf("[%d,%d] [%d,%d]\n",i + 1,j + 1,i + 1,j);
			//cout << C[i + 1][j + 1] << ' ' << R[i + 1][j] << endl;
			if (j < i && C[j + 1][i + 1]) build(id(i,j),id(i,j + 1),C[j + 1][i + 1]);
			if (i < n - 1 && R[j][i + 1]) build(id(i,j),id(i + 1,j),R[j][i + 1]);
		}
	S = 0; T = n * (n - 1) / 2 + 1;
	for (int i = 1; i <= n - 1; i++) if (C[1][i + 1]) build(S,id(i,1),C[1][i + 1]);
	for (int i = 1; i <= n - 1; i++) if (R[i][n]) build(id(n - 1,i),T,R[i][n]);
	dijkstra();
	if (d[T] != INF) printf("%lld\n",d[T]);
	else puts("-1");
	return 0;
}

posted @ 2020-07-17 11:20  Mychael  阅读(160)  评论(0编辑  收藏  举报