HDU 3416

it2022-05-08  10

//题目大意:求两点之间最短路的条数,但是前提是已走过的路径不能重复//题目类型:最大流+最短路径//解题思路:首先用Dijkstra求出两点之间的最短路,然后判断每条边是否在最短路上,如果在最短路上,则流量自增1 ,然后求出最大流 #include <iostream>#include <algorithm>#include <queue>#include <cstdio>//#include <conio.h>using namespace std;                                 const int narray = 1010;              const int marray = 100010;const int INF=0x7fffffff;  struct edge_T {     int u;   //起点(为了最大流建图方便)      int v;   //终点      int w;     edge_T *next;}*adj[narray], edges[marray],*readj[narray],reedges[marray];      bool final[marray];struct node_T {                   int v;     int len;     bool operator < (const node_T &nod) const      {          return len > nod.len;     }};int edgenum,reedgenum;              //记录边的总数 int vn,en;             //记录定点数和边数 int src,des;int dista[narray],distb[narray];

void addEdge(int u, int v, int w) {         edge_T *ptr = &edges[edgenum];     ptr->u = u;     ptr->v = v;     ptr->w = w;     ptr->next = adj[u];    //往前插入边      adj[u] = ptr;     edgenum++;}void addReedge(int u,int v,int w){     edge_T *ptr = &reedges[reedgenum];     ptr->u = u;     ptr->v = v;     ptr->w = w;     ptr->next = readj[u];    //往前插入边      readj[u] = ptr;     reedgenum++;}int dijkstra(int s,int t,int dist[],int flag) {            int i;          priority_queue <node_T> Q;            //使用优先级队列实现      node_T cur;     edge_T *ptr;     cur.v = s;     cur.len = 0;     Q.push(cur);     for(int i = 1; i <= vn; i ++)      {          dist[i] = INF;         }            dist[s] = 0;     while(!Q.empty())      {          int v = Q.top().v;               //优先级队列使用top()           int len = Q.top().len;          Q.pop();          if(dist[v]!=len) continue;          if(flag == 1)  ptr = adj[v];          else ptr = readj[v];          for(; ptr; ptr = ptr -> next)           {               int u = ptr -> v;               int w = ptr -> w;               if(dist[v] + w < dist[u])                {                    dist[u] = dist[v] + w;                    cur.v = u;                    cur.len = dist[u];                    Q.push(cur);                                   }          }     }     return dist[t]; }

int capacity[narray][narray];     int pre[narray];                   int num[narray];                     int d[narray];                       

void init(int src,int des)              {     int i,j;     queue<int> myqueue;     myqueue.push(des);     memset(num,0,sizeof(num));     for(i=1;i<=vn;++i)              d[i] = INF;     d[des] = 0;                  num[0] = 1;     int frontint;     while(!myqueue.empty())       {         frontint = myqueue.front();myqueue.pop();         for(i=1;i<=vn;++i)         {             if(d[i]>=vn && capacity[i][frontint]>0)                {                 d[i] = d[frontint]+1;                 myqueue.push(i);                   num[d[i]]++;                  }                           }     }}int findarc(int t)              {    int i,j;    for(i=1;i<=vn;++i)    {        if(capacity[t][i]>0 && d[t]==d[i]+1) return i;    }    return -1;}int relabel(int t)              {    int i,j;    int mm = INF;    for(i=1;i<=vn;++i)    {        if(capacity[t][i]>0) mm = min(mm,d[i]+1);     }    return mm==INF?vn:mm;}int maxFlow(int src,int des){    int sumflow = 0;    int delta;    int i=src;          int j;    memset(pre,-1,sizeof(pre));        while(d[src]<vn)    {       j = findarc(i);       if(j>=0)       {           pre[j] = i;           i = j;                      if(i==des)                    {               delta = INF;               for (i=des;i!=src;i=pre[i]) delta=min(delta,capacity[pre[i]][i]);                   for (i=des;i!=src;i=pre[i]) capacity[pre[i]][i] -= delta, capacity[i][pre[i]] += delta;                sumflow += delta;           }       }       else       {           int x = relabel(i);           num[x]++;           num[d[i]]--;           if(num[d[i]]==0) return sumflow;                d[i] = x;           if(i!=src) i =pre[i];                  }    }    return sumflow;}//见图并求最大流 void buildAndMaxFlow(int res){     int i,j;     memset(capacity,0,sizeof(capacity));          for(i=1;i<edgenum;++i)       //遍历所有的边(此处使用edgenum,因为可能存在负权回路的情况)      {          int u = edges[i].u;           int v = edges[i].v;          int w = edges[i].w;          if(dista[u]+distb[v]+w==res)     //如果边的起点到源点的距离+边的权值+边的终点到汇点的距离等于汇点到源点的距离              {              capacity[u][v]++;          }     }     init(src,des);            //在求最大流之前首先初始化标顶      printf("%d\n",maxFlow(src,des));}int main() {      //freopen("1.txt","r",stdin);      int t;      int i;      int res;      scanf("%d",&t);      while(t--)      {          scanf("%d %d", &vn, &en);          for(i = 1; i <= vn; i ++)           {               adj[i] = NULL;                //初始化邻接表的指针                readj[i] = NULL;          }          edgenum = 1;                       //初始化边数           reedgenum =1;          int u, v;          int w;          for(i = 1; i <= en; i ++)           {                       scanf("%d%d%d", &u, &v, &w);                if(u==v) continue;    //判断是否有环                addEdge(u, v, w);               addReedge(v,u,w);          }          scanf("%d%d",&src,&des);          //分别求出途中各点到源点和终点之间的距离           dijkstra(src,des,dista,1);          res = dijkstra(des,src,distb,2);          buildAndMaxFlow(res);      }           //getch();      return 0;}

转载于:https://www.cnblogs.com/north_dragon/archive/2010/06/07/1753491.html


最新回复(0)