题目链接:传送门
题目大意:自行参考
题解:首先,观察得知肯定要先求一个最短路(这不是废话么)
然后可以求出最短路网(就是在s到某个点x的某一条最短路上的边的集合)
其中最短路网上的边(u,v,w)满足dist[u]+w=dist[v]。
然后,如果你割掉的不是最短路网上的边,那么显然无论割多少都不会影响答案(因为你总是只沿着最短路网上的边走),所以只考虑这些边。
如果你割了一些最短路网上的边,但s和t仍然联通,那么s-t最短路不变,这是显然的。
所以压迫删去一些边使得s-t不联通,删边要付出代价。
这不就是最小割嘛!
辣么说这个题就水过去了
1A好评!QwQ
//AHOI 2006
//BZOJ 1266
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<climits>
#define MAXN 600
#define MAXM 124750*2+10
#define INF INT_MAX
#define build_edge(u,v,c) add_edge(u,v,c),add_edge(v,u,0)
using namespace std;
struct enode{
int to,wgt,cost;
enode(int _to,int _wgt,int _cost)
{
to=_to;
wgt=_wgt;
cost=_cost;
}
};
vector<enode> g[MAXN];
struct heapnode{
int to,wgt;
heapnode(int _to,int _wgt)
{
to=_to;
wgt=_wgt;
}
bool operator<(const heapnode &hp)const
{
return this->wgt>hp.wgt;
}
};
priority_queue<heapnode> heap;
int dist[MAXN];
struct edges{
int to,pre,wgt,resf;
}e[MAXM];
int lev[MAXN],cur[MAXN],h[MAXN],etop;
queue<int> q;bool vis[MAXN];
int add_edge(int from,int to,int cap)
{
etop++;
e[etop].to=to;
e[etop].resf=cap;
e[etop].pre=h[from];
h[from]=etop;
return 0;
}
bool bfs(int s,int t)
{
memset(vis,false,sizeof(vis));
memset(lev,0,sizeof(lev));
while(!q.empty()) q.pop();
q.push(s);lev[s]=0;vis[s]=true;
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=h[x];i;i=e[i].pre)
if(!vis[e[i].to]&&e[i].resf)
{
vis[e[i].to]=true;
lev[e[i].to]=lev[x]+1;
q.push(e[i].to);
}
}
return vis[t];
}
int dfs(int s,int t,int a)
{
if(s==t||!a) return a;
int flow=0,f;
for(int &i=cur[s];i;i=e[i].pre)
if(lev[e[i].to]==lev[s]+1&&(f=dfs(e[i].to,t,min(a,e[i].resf)))>0)
{
flow+=f;a-=f;e[i].resf-=f;
e[((i-1)^1)+1].resf+=f;
if(!a) break;
}
return flow;
}
int main()
{
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int u,v,t,c;
scanf("%d%d%d%d",&u,&v,&t,&c);
g[u].push_back(enode(v,t,c));
g[v].push_back(enode(u,t,c));
}
for(int i=1;i<=n;i++) dist[i]=INF;
heap.push(heapnode(1,dist[1]=0));
for(int i=1;i<=n;i++)
{
int x=heap.top().to;heap.pop();
if(vis[x]) continue;
vis[x]=true;
for(int i=g[x].size()-1;i>=0;i--)
if(!vis[g[x][i].to]&&dist[g[x][i].to]>dist[x]+g[x][i].wgt)
{
dist[g[x][i].to]=dist[x]+g[x][i].wgt;
heap.push(heapnode(g[x][i].to,dist[g[x][i].to]));
}
}
printf("%d\n",dist[n]);
for(int i=1;i<=n;i++)
for(int j=g[i].size()-1;j>=0;j--)
{
int u=i,v=g[i][j].to,w=g[i][j].wgt,c=g[i][j].cost;
if(dist[u]+w==dist[v]) build_edge(u,v,c);
}
int flow=0,s=1,t=n;
while(bfs(s,t))
{
for(int i=s;i<=t;i++)
cur[i]=h[i];
flow+=dfs(s,t,INF);
}
printf("%d\n",flow);return 0;
}