zoukankan      html  css  js  c++  java
  • 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
    ",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]
    ",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
    ",d[T]);
    	else puts("-1");
    	return 0;
    }
    
    
  • 相关阅读:
    VS2008编译出现问题:error C2485: “__restrict”: 无法识别的扩展属性 解决办法
    精度试验结果报告Sleep, GetTickCount, timeGetTime, QueryPerformanceCounter
    error C2872: 'ULONG_PTR' : ambiguous symbol
    无法删除文件:无法读源文件或磁盘”
    如何HOOK桌面窗口消息
    批处理常用特殊符号
    我的Hook学习笔记
    代码注入的三种方法
    Ubuntu 安装 “宋体,微软雅黑,WPS Office的symbol、wingdings、wingdings 2、wingdings 3、webding字体,Consolas雅黑混合版编程字体” 等 Windows 7 下的字体(转)
    Delphi中如何将 Exe 程序或其他资料打包在内,使用时再释放使用(转)
  • 原文地址:https://www.cnblogs.com/Mychael/p/13328776.html
Copyright © 2011-2022 走看看