題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=5294
題意:給你n個墓室,m條路徑,一個人在1號墓室(起點),另一個人在n號墓室(終點),起點的那個人只有通過最短路徑才能追上終點的那個人,而終點的那個人能切斷任意路徑。
第一問——終點那人要使起點那人不能追上的情況下可以切的最少的路徑數,輸出最少的路徑數
第二問——起點那人能追上終點那人的情況下,終點那人能切斷的最多的路徑數,輸出最多的路徑數
思路:要使起點那人無法追上,只要使他的最短路徑不存在就好了,那麼只要在最短路徑上使每條路的流量爲1,並球出1-n的最大流就是,能切斷的最少的路徑數;
要是起點那人能追上,那麼只要他的最短路徑存在就可以了,並在這些最短路徑中求出路徑數最少的那條,那麼最多的路徑數就是m-路徑數最少的那條的路徑數。
代碼:
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#include <queue>
#include <algorithm>
#include <vector>
using namespace std;
#define LL __int64
#define INF 0x3f3f3f3f
const int MAXN=20005;
struct qnode
{
int v;
int c;
qnode(int _v=0,int _c=0):v(_v),c(_c){}
bool operator <(const qnode &r)const
{
return c>r.c;
}
};
bool vis[2005];
int dist[2005];
int mp[2005][2005];
void Dijkstra(int n,int start)//求最短路徑大小
{
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++)dist[i]=INF;
priority_queue<qnode>que;
while(!que.empty())que.pop();
dist[start]=0;
que.push(qnode(start,0,0));
qnode tmp;
while(!que.empty())
{
tmp=que.top();
que.pop();
int u=tmp.v;
if(vis[u])continue;
vis[u]=true;
for(int i=1;i<=n;i++)
{
if(!vis[i]&&mp[u][i]<INF&&dist[i]>dist[u]+mp[u][i])
{
dist[i]=dist[u]+mp[u][i];
que.push(qnode(i,dist[i]));
}
}
}
}
int mp2[2005][2005];
void Dijkstra1(int n,int start)//求最短的路數
{
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++)dist[i]=INF;
priority_queue<qnode>que;
while(!que.empty())que.pop();
dist[start]=0;
que.push(qnode(start,0,0));
qnode tmp;
while(!que.empty())
{
tmp=que.top();
que.pop();
int u=tmp.v;
int gg=tmp.flag+1;
if(vis[u])continue;
vis[u]=true;
for(int i=1;i<=n;i++)
{
if(!vis[i]&&mp2[u][i]<INF&&dist[i]>dist[u]+mp2[u][i])
{
dist[i]=dist[u]+mp2[u][i];
que.push(qnode(i,dist[i]));
}
}
}
}
struct edge
{
int from,to,cap,flow;
edge(){}
edge(int f,int t,int c,int fl):from(f),to(t),cap(c),flow(fl){}
};
struct Dinic
{
int n,m,s,t;
vector<edge> edges;
vector<int> G[MAXN];
int cur[MAXN];
int d[MAXN];
bool vis[MAXN];
void init(int n,int s,int t)
{
this->n=n, this->s=s, this->t=t;
edges.clear();
for(int i=0;i<n;i++) G[i].clear();
}
void AddEdge(int from,int to,int cap)
{
edges.push_back( edge(from,to,cap,0) );
edges.push_back( edge(to,from,0,0) );
m = edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool BFS()
{
queue<int> Q;
Q.push(s);
memset(vis,0,sizeof(vis));
d[s]=0;
vis[s]=true;
while(!Q.empty())
{
int x=Q.front(); Q.pop();
for(int i=0;i<G[x].size();++i)
{
edge& e=edges[G[x][i]];
if(!vis[e.to] && e.cap>e.flow)
{
d[e.to]=1+d[x];
vis[e.to]=true;
Q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int x,int a)
{
if(x==t || a==0) return a;
int flow=0,f;
for(int& i=cur[x];i<G[x].size();++i)
{
edge& e=edges[G[x][i]];
if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0)
{
e.flow +=f;
edges[G[x][i]^1].flow -=f;
flow +=f;
a-=f;
if(a==0) break;
}
}
return flow;
}
int max_flow()
{
int ans=0;
while(BFS())
{
memset(cur,0,sizeof(cur));
ans += DFS(s,INF);
}
return ans;
}
}DC;
int ggg[2005][2005];
int main()
{
int n,m,i,j,a,b,c;
while(~scanf("%d%d",&n,&m))
{
DC.init(n,1,n);
memset(ggg,0,sizeof(ggg));
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
mp[i][j]=mp2[i][j]=INF;
for(i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
if(mp[a][b]>c)
{
mp[a][b]=c;
mp[b][a]=c;
ggg[a][b]=1;
ggg[b][a]=1;
}
else if(mp[a][b]==c)
{
ggg[a][b]++;
ggg[b][a]++;
}
}
Dijkstra(n,1);
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(mp[i][j]+dist[i]==dist[j])
{
for(int k=0;k<ggg[i][j];k++)
DC.AddEdge(i,j,1);
mp2[i][j]=1;
}
}
}
Dijkstra1(n,1);
printf("%d %d\n",DC.max_flow(),m-dist[n]);
}
return 0;
}