NC23347. Tachibana Kanade And Dream City
描述
输入描述
输入的第一行为两个正整数 n,m。
接下来有 n 行,每行两个整数 。
接下来有 m 行,每行三个整数 。
以上各值的意义如「题目描述」所示。
输出描述
输出一个整数,表示最小值,如果不可能就输出-1。
示例1
输入:
3 2 6 2 2 4 3 7 1 2 10 2 3 20
输出:
20
说明:
我们安排 1 点到 2 点流 4 个单位的水,2 点到3 点流2个单位的水,同时进行,显然时间为 20C++14(g++5.4) 解法, 执行用时: 161ms, 内存消耗: 2664K, 提交时间: 2020-04-10 21:12:26
#include <stdio.h> #include <algorithm> #include <queue> #include <string.h> #define int long long #define ll long long using namespace std; const int N=410,M=100010; int head[N],ver[M],nex[M],pre[N],dep[N],w[M]; ll f[210][210],val[210],c[210]; int n,m,s,t,tot,maxflow; ll sum; void add(int u,int v,int d) { ver[++tot]=v;nex[tot]=head[u];w[tot]=d;head[u]=tot; } bool bfs() { memset(dep,0,sizeof(dep)); queue<int>q; q.push(s);dep[s]=1; while(q.size()) { int u=q.front();q.pop(); for(int i=head[u];i;i=nex[i]) { int v=ver[i]; if(dep[v]||!w[i])continue; dep[v]=dep[u]+1; q.push(v); if(v==t)return 1; } } return 0; } int dinic(int u,int flow) { if(u==t)return flow; int res=flow,k; for(int i=head[u];i&&res;i=nex[i]) { int v=ver[i]; if(w[i]&&dep[v]==dep[u]+1) { k=dinic(v,min(res,w[i])); if(!k)dep[v]=0; w[i]-=k;w[i^1]+=k; res-=k; } } return flow-res; } void floyd() { for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f[i][j]=min(f[i][j],f[i][k]+f[k][j]); } bool check(ll mid) { memset(head,0,sizeof(head)); tot=1;ll maxflow=0; for(int i=1;i<=n;i++)add(s,i,val[i]),add(i,s,0),add(i,i+n,1e9),add(i+n,i,0),add(i+n,t,c[i]),add(t,i+n,0); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(f[i][j]<=mid&&i!=j)add(i,j+n,1e9),add(j+n,i,0); int flow=0; while(bfs()) while(flow=dinic(s,1e18))maxflow+=flow; return maxflow>=sum; } ll solve() { ll l=0,r=1e18; while(l<r) { ll mid=(l+r)/2; if(check(mid))r=mid; else l=mid+1; } if(r==1e18)return -1; return l; } signed main() { scanf("%lld%lld",&n,&m); s=0,t=2*n+1; memset(f,0x3f,sizeof(f)); for(int i=1;i<=n;i++)scanf("%lld%lld",&val[i],&c[i]),sum+=val[i]; for(int i=1;i<=m;i++) { int u,v,z; scanf("%lld%lld%lld",&u,&v,&z); f[u][v]=f[v][u]=min(f[u][v],z); } floyd(); printf("%lld\n",solve()); }
C++11(clang++ 3.9) 解法, 执行用时: 178ms, 内存消耗: 2784K, 提交时间: 2019-09-26 00:26:39
#pragma GCC optimize(2) #include<bits/stdc++.h> #define int long long using namespace std; const int inf=0x3f3f3f3f3f3f3f3f; const int N=1e4+10,M=1e5+10; int n,m,g[210][210],s,t,h[N],res,v[N],val[N]; int head[N],nex[M],to[M],w[M],tot=1; inline void ade(int a,int b,int c){ to[++tot]=b; w[tot]=c; nex[tot]=head[a]; head[a]=tot; } inline void add(int a,int b,int c){ ade(a,b,c); ade(b,a,0); } void floyd(){ for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) g[i][j]=min(g[i][j],g[i][k]+g[k][j]); } int bfs(){ memset(h,0,sizeof h); h[s]=1; queue<int> q; q.push(s); while(q.size()){ int u=q.front(); q.pop(); for(int i=head[u];i;i=nex[i]){ if(w[i]&&!h[to[i]]){ h[to[i]]=h[u]+1; q.push(to[i]); } } } return h[t]; } int dfs(int x,int f){ if(x==t) return f; int fl=0; for(int i=head[x];i&&f;i=nex[i]){ if(w[i]&&h[to[i]]==h[x]+1){ int mi=dfs(to[i],min(f,w[i])); w[i]-=mi; w[i^1]+=mi; fl+=mi; f-=mi; } } if(!fl) h[x]=-1; return fl; } int dinic(){ int res=0; while(bfs()) res+=dfs(s,inf); return res; } int check(int mid){ tot=1; memset(head,0,sizeof head); for(int i=1;i<=n;i++) add(s,i,v[i]),add(i,i+n,1e9),add(i+n,t,val[i]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(g[i][j]<=mid&&i!=j){ add(i,j+n,1e9); } return dinic()>=res; } int bsearch(){ int l=1,r=1e18; while(l<r){ int mid=l+r>>1; if(check(mid)) r=mid; else l=mid+1; } if(r==1e18) return -1; else return l; } signed main(){ cin>>n>>m; t=n*2+1; memset(g,0x3f,sizeof g); for(int i=1;i<=n;i++) cin>>v[i]>>val[i],res+=v[i]; while(m--){ int a,b,c; cin>>a>>b>>c; g[a][b]=g[b][a]=min(g[a][b],c); } floyd(); cout<<bsearch()<<endl; return 0; }