hdu5249 Tricks Device(網絡流最大匹配)
阿新 • • 發佈:2017-07-10
nic ack efi trac 保存 trick 題意 n) push
分析題意可知:
1、最少須要切斷多少邊使吳不能找到張(題意吳僅僅能走最短路徑上面的邊),對從起點到終點的最短路徑又一次建圖,每條邊的權值為1。求最大流就可以
2、在吳能夠找到張的前提下,最多能夠切斷邊的數量:僅僅須要在全部最短路徑中尋找一條經過邊數量最少的最短路徑,用邊的總數減去它就可以(逆向思維)
代碼例如以下:
#include <cstdio> #include <cstring> #include <vector> #include <queue> #define MAXN 2010 #define INF 1e9+7 using namespace std; struct Edge { int v,cost,cap;///v代表邊的還有一個頂點。cost代表邊的代價,cap代表反向邊的位置 Edge(int _v=0,int _cost=0,int _cap=0):v(_v),cost(_cost),cap(_cap) {} }; vector<Edge> g[MAXN];///保存地圖 vector<int> pre[MAXN];///記錄最短路徑上每一個節點的父節點,用於構建網絡流 int flag[MAXN][MAXN];///解決重邊問題 int d[MAXN];///記錄到達某一點的最短路徑所經過的最短的邊,用於求解問題2 int dist[MAXN]; 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; } }; int n,m; int level[MAXN]; void Dijkstra(int s); void addedge(int u,int v,int w,int cap); void built(int u); int DINIC(int s,int t); int DFS(int now,int maxf,int t); bool makelevel(int s,int t); int main() { //FILE* fp = fopen("C:\\Users\\Crazy_Bear\\Desktop\\數據\\data1007\\1007.in","rw"); while(scanf("%d%d",&n,&m)==2) { memset(g,0,sizeof(g)); memset(flag,0,sizeof(flag)); int x,y,v; for(int i=1; i<=m; ++i) { //fscanf(fp,"%d%d%d",&x,&y,&v); scanf("%d%d%d",&x,&y,&v); flag[x][y]++;///記錄重邊的數量 addedge(x,y,v,0); flag[y][x]++; addedge(y,x,v,0); } Dijkstra(1); memset(g,0,sizeof(g)); built(n);///又一次建圖 printf("%d %d\n",DINIC(1,n),m-d[n]); } // fclose(fp); return 0; } void addedge(int u,int v,int w,int cap) { g[u].push_back(Edge(v,w,cap)); } void Dijkstra(int s) { bool vis[MAXN]; for(int i=1; i<=n; ++i) { vis[i]=false; dist[i]=INF; pre[i].clear(); d[i]=INF; } priority_queue<qnode> pq; while(!pq.empty()) pq.pop(); dist[s]=0; d[s]=0; pq.push(qnode(s,0)); qnode tmp; while(!pq.empty()) { tmp=pq.top(); pq.pop(); int u=tmp.v; if(vis[u]) continue; vis[u]=true; for(int i=0; i<g[u].size(); ++i) { int v=g[u][i].v; int cost=g[u][i].cost; if(dist[v]==dist[u]+cost) { pre[v].push_back(u);///在求解最短路徑的過程中記錄父節點 d[v]=min(d[u]+1,d[v]); } else if(dist[v]>dist[u]+cost) { dist[v]=dist[u]+cost; pq.push(qnode(v,dist[v])); d[v]=d[u]+1; pre[v].clear(); pre[v].push_back(u); } } } } void built(int u) { if(u==1) return; int len=pre[u].size(); for(int i=0; i<len; ++i) { if(flag[pre[u][i]][u]>0) { addedge(pre[u][i],u,1,g[u].size()); flag[pre[u][i]][u]--; addedge(u,pre[u][i],1,g[pre[u][i]].size()-1); flag[u][pre[u][i]]--; built(pre[u][i]); } } } bool makelevel(int s,int t) { memset(level,0,sizeof(level)); level[s]=1; int que[MAXN]; int iq=0; que[iq++]=s; int top; for(int i=0; i<iq; ++i) { top=que[i]; if(top==t) return true; int len=g[top].size(); for(int i=0; i<len; ++i) { if(!level[g[top][i].v]&&g[top][i].cost) { que[iq++]=g[top][i].v; level[g[top][i].v]=level[top]+1; } } } return false; } int DFS(int now,int maxf,int t) { if(now==t) return maxf; int ret=0,f; int len=g[now].size(); for(int i=0; i<len; ++i) { if(g[now][i].cost&&level[g[now][i].v]==level[now]+1) { f=DFS(g[now][i].v,min(maxf-ret,g[now][i].cost),t); g[now][i].cost-=f; g[g[now][i].v][g[now][i].cap].cost+=f; ret+=f; if(ret==maxf) return ret; } } return ret; } int DINIC(int s,int t) { int ans=0; while(makelevel(s,t)) ans+=DFS(s,INF,t); return ans; }
hdu5249 Tricks Device(網絡流最大匹配)