[SDOI2009] 晨跑
作者:互联网
[SDOI2009] 晨跑
序
晨跑?是该减肥了
正文
这真的是道水题。按照常理,我讲讲我的想法。
首先,不难看出这题是到图论的题。然后,他的要求是在各个路径上每个结点都不能相遇。所以自然想到拆点。注意结点的编号。然后,就没什么重要的。
/* make by ltao */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <deque>
#include <stack>
#include <cmath>
#include <vector>
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define sz 666666
#define fake int
#define get() getchar()
int read(){
int x=0;bool f=0;
char ch=get();
while(ch<'0'||ch>'9'){
if(ch=='-') f=1;
ch=get();
}
while(ch<='9'&&ch>='0'){
x=(x<<1)+(x<<3)+(ch-'0');
ch=get();
}
return f?-x:x;
}
using namespace std;
const int Maxn=404,Maxm=1e5+11;
int n,m,h[Maxn],s,t,x,y,z,cur[Maxn],cnt,maxflow,mincost,dis[Maxn];
bool vis[Maxn];
struct Edge{
int fr,to,lac,flow,cost;
void insert(int x,int y,int z,int w){
to=y;fr=x;
lac=h[x];h[x]=cnt++;
flow=z;cost=w;
}
}edge[Maxm];
int mappn(int u){return u==1?1:u==n?u*2-2:u*2-1;}//后面的点
int mapp1(int u){return u==1?u:u*2-2;}//前面的点
int val=-1;// slf 优化
bool spfa(int s,int t){
memset(dis,63,sizeof dis);
memcpy(cur,h,sizeof cur);
deque<int> q;q.push_back(s);dis[s]=0;vis[s]=1;
while(!q.empty()){
int fr=q.front();
q.pop_front();vis[fr]=0;
for(int i=h[fr];i!=-1;i=edge[i].lac){
int to=edge[i].to;
if(edge[i].flow&&dis[to]>dis[fr]+edge[i].cost){
dis[to]=dis[fr]+edge[i].cost;
if(!vis[to]){
vis[to]=1;
if(q.size()>0)
if(dis[to]-val>=dis[*(q.begin())]) q.push_back(to);
else q.push_front(to);
else q.push_back(to);
}
}
}
}
return dis[t]!=0x3f3f3f3f;
}
int dfs(int u,int min1){
if(u==t) return min1;
int sum=min1;vis[u]=1;
for(int i=cur[u];i!=-1;i=edge[i].lac){
int to=edge[i].to;
if(!edge[i].flow||vis[to]||dis[u]+edge[i].cost!=dis[to]) continue;
cur[u]=i;int ret=dfs(to,min(sum,edge[i].flow));
sum-=ret;edge[i].flow-=ret;edge[i^1].flow+=ret;mincost+=ret*edge[i].cost;
if(!sum) break;
}
vis[u]=0;
return min1-sum;
}
void zkwDinic(int s,int t){
while(spfa(s,t))
maxflow+=dfs(s,0x3f3f3f3f);
}
int main(){
freopen("a.in","r",stdin);
n=read();m=read();s=1;t=n*2-2;memset(h,-1,sizeof h);
for(int i=2;i<n;i++){
edge[cnt].insert(i*2-2,i*2-1,1,0);
edge[cnt].insert(i*2-1,i*2-2,0,0);
}
//拆点
for(int i=1;i<=m;i++){
x=read();y=read();z=read();
x=mappn(x);y=mapp1(y);
edge[cnt].insert(x,y,1,z);
edge[cnt].insert(y,x,0,-z);
}
zkwDinic(s,t);
printf("%d %d",maxflow,mincost);
return 0;
}
话说zkw真是有用
嵬
我还是喜欢胖胖的我
标签:int,sum,晨跑,vis,edge,SDOI2009,include,dis 来源: https://www.cnblogs.com/zhltao/p/12339793.html