2020牛客暑期多校训练营(第二场) I题题解
题目链接
题解
将每个区间看做二维平面上的点,我们的目标就是阻止从\((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;
}