bzoj2007 NOI2010 海拔(对偶图)
程序员文章站
2022-05-27 15:18:30
80分(最小割)思路
先考虑如果没有题目中东南角为1那个限制的话会怎样。
那么只要让每个点的海拔都是0就行了。这样不论怎样走,最后的答案都是0. ......
80分(最小割)思路
先考虑如果没有题目中东南角为\(1\)那个限制的话会怎样。
那么只要让每个点的海拔都是\(0\)就行了。这样不论怎样走,最后的答案都是0.
然后再考虑那个东南角为\(1\)的限制表达了什么。其实说明了最后的答案一定是右下角一部分海拔全部为\(1\),左上角一部分海拔全部为\(0\)。
所以这样只要找到分界点就行了。
这就是最小割的裸题啊。以\((1,1)\)为起点,\((n+1,n+1)\)为终点跑一遍最小割就行了。
100分(对偶图)思路
直接最小割过不去后面的大数据。所以要用对偶图优化一下。
平面图就是像题目中这样两条边的交点都是顶点的图。
如图
图中\(9\)个方格叫做平面图的面。对于一个平面图的对偶图,就是将平面图中的每个边两边的两个面连接起来。
上图的对偶图就长这样
红色部分就是对偶图了。
然后只要将原图转化成对偶图之后,跑最短路就行了。
80(90)分代码
/* * @author: wxyww * @date: 2019-02-12 11:28:33 * @last modified time: 2019-02-12 15:42:39 */ #include<cstdio> #include<iostream> #include<cstdlib> #include<cmath> #include<ctime> #include<bitset> #include<cstring> #include<queue> using namespace std; typedef long long ll; #define num(x,y) (x - 1) * (n + 1) + y const int n = 500000,m = 10000000,inf = 1e9; ll read() { ll x=0,f=1;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 x*f; } struct node { int v,nxt,w; }e[m]; int head[n],ejs = 1; void add(int u,int v,int w) { e[++ejs].v = v;e[ejs].nxt = head[u];head[u] = ejs;e[ejs].w = w; e[++ejs].v = u;e[ejs].nxt = head[v];head[v] = ejs;e[ejs].w = 0; } queue<int>q; int dep[n]; int s,t; int bfs() { memset(dep,0,sizeof(dep)); while(!q.empty()) q.pop(); dep[s] = 1;q.push(s); while(!q.empty()) { int u = q.front();q.pop(); for(int i = head[u];i;i = e[i].nxt) { int v = e[i].v; if(!dep[v] && e[i].w) { q.push(v); dep[v] = dep[u] + 1; if(v == t) return 1; } } } return 0; } int cur[n]; int dfs(int u,int now) { if(u == t) return now; int ret = 0; for(int &i = cur[u];i;i = e[i].nxt) { int v = e[i].v; if(dep[v] == dep[u] + 1 && e[i].w) { int k = dfs(v,min(now - ret,e[i].w)); e[i].w -= k; e[i ^ 1].w += k; ret += k; if(now == ret) return ret; } } return ret; } int dinic() { int ans = 0; while(bfs()) { memcpy(cur,head,sizeof(cur)); ans += dfs(s,inf); } return ans; } int main() { int n = read(); s = num(1,1);t = num(n + 1,n + 1); for(int i = 1;i <= n + 1;++i) { for(int j = 1;j <= n;++j) { int w = read(); add(num(i,j),num(i,j + 1),w); } } for(int i = 1;i <= n;++i) { for(int j = 1;j <= n + 1;++j) { int w = read(); add(num(i,j),num(i + 1,j),w); } } for(int i = 1;i <= n + 1; ++i) { for(int j = 1;j <= n;++j) { int w = read(); add(num(i,j + 1),num(i,j),w); } } for(int i = 1;i <= n;++i) { for(int j = 1;j <= n + 1; ++j) { int w = read(); add(num(i + 1,j),num(i,j),w); } } cout<<dinic(); return 0; }
100分代码
/* * @author: wxyww * @date: 2019-02-12 14:54:58 * @last modified time: 2019-02-12 15:31:30 */ #include<cstdio> #include<iostream> #include<cstdlib> #include<cmath> #include<ctime> #include<bitset> #include<queue> #include<cstring> using namespace std; typedef long long ll; const int n = 501000,m = 10000000; #define pi pair<int,int> ll read() { ll x=0,f=1;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 x*f; } priority_queue<pi,vector<pi>,greater<pi> >q; struct node { int v,nxt,w; }e[m]; int head[n],ejs; void add(int u,int v,int w) { e[++ejs].v = v;e[ejs].w = w;e[ejs].nxt = head[u];head[u] = ejs; } int s,t; int dis[n],vis[n]; int dij() { memset(dis,0x3f,sizeof(dis)); q.push(make_pair(0,s)); dis[s] = 0; for(int i = 1;i <= t;++i) { if(q.empty()) break; pi k = q.top(); while(vis[k.second] && !q.empty()) k = q.top(),q.pop(); int u = k.second; if(vis[u]) break; vis[u] = 1; for(int i = head[u];i;i = e[i].nxt) { int v = e[i].v; if(vis[v]) continue; if(dis[v] > dis[u] + e[i].w) { dis[v] = dis[u] + e[i].w; q.push(make_pair(dis[v],v)); } } } return dis[t]; } int main() { int n = read(); int now; s = n * n + 1,t = s + 1; now = 1; for(int i = 1;i <= n + 1;++i) { for(int j = 1;j <= n;++j,++now) { int w = read(); if(i == 1) add(now,t,w); else if(i == n + 1) add(s,now - n,w); else add(now,now - n,w); } } now = 1; for(int i = 1;i <= n;++i) { for(int j = 1;j <= n + 1;++j,++now) { int w = read(); if(j == 1) add(s,now,w); else if(j == n + 1) add(--now,t,w); else add(now - 1,now,w); } } now = 1; for(int i = 1;i <= n + 1;++i) { for(int j = 1;j <= n;++j,++now) { int w = read(); if(i == 1 ||i == n + 1) continue; add(now - n,now,w); } } now = 1; for(int i = 1;i <= n;++i) { for(int j = 1;j <= n + 1;++j,++now) { int w = read(); if(j == 1 || j == n + 1) continue; add(now,now - 1,w); } --now; } cout<<dij(); return 0; }
上一篇: linux之yum安装mysql
下一篇: 关于微信登录开发记录