生成树&最短路总结篇

本文系转载,原创请访问:http://blog.youkuaiyun.com/zhou_yujia/article/details/51427382

1、模板题  我是用prim搞得 给出每点坐标求最小生成树

hdu1162Eddy's picture 最小生成树

  1. #include <iostream>  
  2. #include<cstdio>  
  3. #include<cstring>  
  4. #include<cmath>  
  5. using namespace std;  
  6. int flag1=0;  
  7. double sum;  
  8. double arr_list[110][110];  
  9. struct Edge  
  10. {  
  11.      int point;  
  12.      double lowcost;  
  13.      int flag;  
  14. };  
  15. Edge edge[12100];  
  16. struct Point  
  17. {  
  18.      double x,y;  
  19. }point[110];  
  20. double prim(int n)  
  21. {  
  22.      int i,j,k=1,flag;  
  23.      double min,sum2=0;  
  24.      j=1;  
  25.      for(i=1;i<=n;i++)  
  26.      {  
  27.           if(i!=j)  
  28.           {  
  29.                edge[i].point=i;  
  30.                edge[i].lowcost=arr_list[j][i];  
  31.                edge[i].flag=0;  
  32.           }  
  33.      }  
  34.      edge[j].lowcost=0;  
  35.      edge[j].flag=1;  
  36.      for(i=2;i<=n;i++)  
  37.      {  
  38.           k=1;  
  39.           min=65535;  
  40.           flag=0;  
  41.           for(j=2;j<=n;j++)  
  42.           {  
  43.                if(edge[j].flag==0&&edge[j].lowcost<min)  
  44.                {  
  45.                     k=j;  
  46.                     min=edge[j].lowcost;  
  47.                     flag=1;  
  48.                }  
  49.           }  
  50.           if(!flag) return -1;  
  51.           sum2+=min;  
  52.           edge[k].flag=1;  
  53.           for(j=2;j<=n;j++)  
  54.           {  
  55.                if(edge[j].flag==0&&arr_list[k][j]<edge[j].lowcost)  
  56.                {  
  57.                     edge[j].point=k;  
  58.                     edge[j].lowcost=arr_list[k][j];  
  59.                }  
  60.           }  
  61.      }  
  62.      return sum2;  
  63. }  
  64. int main()  
  65. {  
  66.    // freopen("cin.txt","r",stdin);  
  67.     int n;  
  68.     while(~scanf("%d",&n))  
  69.     {  
  70.          for(int i=1;i<=n;i++)  
  71.          {  
  72.               cin>>point[i].x>>point[i].y;  
  73.               arr_list[i][i]=65535;  
  74.          }  
  75.          for(int i=1;i<n;i++)  
  76.          {  
  77.               for(int j=i+1;j<=n;j++)  
  78.               {  
  79.                    arr_list[i][j]=sqrt(pow((point[i].x-point[j].x),2)+pow((point[i].y-point[j].y),2));  
  80.                    arr_list[j][i]=arr_list[i][j];  
  81.                    //cout<<arr_list[i][j]<<endl;  
  82.               }  
  83.          }  
  84.          sum=prim(n);  
  85.          printf("%.2lf\n",sum);  
  86.     }  
  87.     return 0;  
  88. }  
#include <iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int flag1=0;
double sum;
double arr_list[110][110];
struct Edge
{
     int point;
     double lowcost;
     int flag;
};
Edge edge[12100];
struct Point
{
     double x,y;
}point[110];
double prim(int n)
{
     int i,j,k=1,flag;
     double min,sum2=0;
     j=1;
     for(i=1;i<=n;i++)
     {
          if(i!=j)
          {
               edge[i].point=i;
               edge[i].lowcost=arr_list[j][i];
               edge[i].flag=0;
          }
     }
     edge[j].lowcost=0;
     edge[j].flag=1;
     for(i=2;i<=n;i++)
     {
          k=1;
          min=65535;
          flag=0;
          for(j=2;j<=n;j++)
          {
               if(edge[j].flag==0&&edge[j].lowcost<min)
               {
                    k=j;
                    min=edge[j].lowcost;
                    flag=1;
               }
          }
          if(!flag) return -1;
          sum2+=min;
          edge[k].flag=1;
          for(j=2;j<=n;j++)
          {
               if(edge[j].flag==0&&arr_list[k][j]<edge[j].lowcost)
               {
                    edge[j].point=k;
                    edge[j].lowcost=arr_list[k][j];
               }
          }
     }
     return sum2;
}
int main()
{
   // freopen("cin.txt","r",stdin);
    int n;
    while(~scanf("%d",&n))
    {
         for(int i=1;i<=n;i++)
         {
              cin>>point[i].x>>point[i].y;
              arr_list[i][i]=65535;
         }
         for(int i=1;i<n;i++)
         {
              for(int j=i+1;j<=n;j++)
              {
                   arr_list[i][j]=sqrt(pow((point[i].x-point[j].x),2)+pow((point[i].y-point[j].y),2));
                   arr_list[j][i]=arr_list[i][j];
                   //cout<<arr_list[i][j]<<endl;
              }
         }
         sum=prim(n);
         printf("%.2lf\n",sum);
    }
    return 0;
}

2、模板题 floyd最短路相加改成相乘

hdu1596find the safest road最短路floyd

  1. #include <iostream>    
  2. #include<cstdio>    
  3. using namespace std;    
  4. double dist[1005][1005];    
  5. int main()    
  6. {    
  7.   //  freopen("cin.txt","r",stdin);    
  8.     int n,q,a,b;    
  9.     while(~scanf("%d",&n))    
  10.     {    
  11.          for(int i=0;i<n;i++)    
  12.          {    
  13.               for(int j=0;j<n;j++)    
  14.               {    
  15.                    scanf("%lf",&dist[i][j]);    
  16.               }    
  17.          }    
  18.          for(int i=0;i<n;i++)    
  19.          {    
  20.               for(int j=0;j<n;j++)    
  21.               {    
  22.                    for(int k=0;k<n;k++)    
  23.                    {    
  24.                         if(dist[j][i]*dist[i][k]>dist[j][k])    
  25.                          dist[j][k]=dist[j][i]*dist[i][k];    
  26.                    }    
  27.               }    
  28.          }    
  29.          scanf("%d",&q);    
  30.          while(q--)    
  31.          {    
  32.               scanf("%d%d",&a,&b);    
  33.               a--;b--;    
  34.               if(dist[a][b]>0.000001)    
  35.               printf("%.3lf\n",dist[a][b]);    
  36.               else puts("What a pity!");    
  37.          }    
  38.     }    
  39.     return 0;    
  40. }    
    #include <iostream>  
    #include<cstdio>  
    using namespace std;  
    double dist[1005][1005];  
    int main()  
    {  
      //  freopen("cin.txt","r",stdin);  
        int n,q,a,b;  
        while(~scanf("%d",&n))  
        {  
             for(int i=0;i<n;i++)  
             {  
                  for(int j=0;j<n;j++)  
                  {  
                       scanf("%lf",&dist[i][j]);  
                  }  
             }  
             for(int i=0;i<n;i++)  
             {  
                  for(int j=0;j<n;j++)  
                  {  
                       for(int k=0;k<n;k++)  
                       {  
                            if(dist[j][i]*dist[i][k]>dist[j][k])  
                             dist[j][k]=dist[j][i]*dist[i][k];  
                       }  
                  }  
             }  
             scanf("%d",&q);  
             while(q--)  
             {  
                  scanf("%d%d",&a,&b);  
                  a--;b--;  
                  if(dist[a][b]>0.000001)  
                  printf("%.3lf\n",dist[a][b]);  
                  else puts("What a pity!");  
             }  
        }  
        return 0;  
    }  

3、稍微转弯的prim

poj2349Arctic Network最小生成树

题意:p个哨所间只有s个卫星通道,但每个哨所都有无线发射器,无线发射的功率随长度增加而增加但是每个都一样,问最小长度?

我们知道prim算法中的步骤是每次加入最小的边,但是并没有将加入的边存储下来,加一个数组存储下来,倒序排序,前s个边用卫星通道就好啦

  1. #include <iostream>    
  2. #include<cstdio>    
  3. #include<cstring>    
  4. #include<cmath>    
  5. #include<algorithm>    
  6. using namespace std;    
  7. int flag1=0;    
  8. int n,s,p;    
  9. double sum;    
  10. double arr_list[504][504];    
  11. double d[503];    
  12. struct Edge    
  13. {    
  14.      int point;    
  15.      double lowcost;    
  16.      int flag;    
  17. };    
  18. Edge edge[505];    
  19. bool cmp(double a,double b)    
  20. {    
  21.      return a>b;    
  22. }    
  23. struct Point    
  24. {    
  25.      double x,y;    
  26. }point[502];    
  27. void prim(int p)    
  28. {    
  29.      int i,j,k=1;    
  30.      double min,sum2=0;    
  31.      j=1;    
  32.      for(i=1;i<=p;i++)    
  33.      {    
  34.           if(i!=j)    
  35.           {    
  36.                edge[i].point=j;    
  37.                edge[i].lowcost=arr_list[j][i];    
  38.                edge[i].flag=0;    
  39.           }    
  40.      }    
  41.      edge[j].lowcost=0;    
  42.      edge[j].flag=1;    
  43.      int l=0;    
  44.      for(i=1;i<p;i++)    
  45.      {    
  46.           min=65535000;    
  47.           for(j=2;j<=p;j++)    
  48.           {    
  49.                if(edge[j].flag==0&&edge[j].lowcost<min)    
  50.                {    
  51.                     k=j;    
  52.                     min=edge[j].lowcost;    
  53.                }    
  54.           }    
  55.           d[l++]=arr_list[k][edge[k].point];    
  56.           //sum2+=min;    
  57.           edge[k].flag=1;    
  58.           for(j=2;j<=p;j++)    
  59.           {    
  60.                if(edge[j].flag==0&&arr_list[k][j]<edge[j].lowcost)    
  61.                {    
  62.                     edge[j].point=k;    
  63.                     edge[j].lowcost=arr_list[k][j];    
  64.                }    
  65.           }    
  66.      }    
  67. }    
  68. int main()    
  69. {    
  70.       //  freopen("cin.txt","r",stdin);    
  71.          cin>>n;    
  72.          while(n--)    
  73.          {    
  74.                cin>>s>>p;    
  75.                for(int i=1;i<=p;i++)    
  76.                {    
  77.                     cin>>point[i].x>>point[i].y;    
  78.                     arr_list[i][i]=65535000;    
  79.                }    
  80.                for(int i=1;i<p;i++)    
  81.                {    
  82.                     for(int j=i+1;j<=p;j++)    
  83.                     {    
  84.                          arr_list[i][j]=sqrt(pow((point[i].x-point[j].x),2)+pow((point[i].y-point[j].y),2));    
  85.                          arr_list[j][i]=arr_list[i][j];    
  86.                    //cout<<arr_list[i][j]<<endl;    
  87.                     }    
  88.                }    
  89.                prim(p);    
  90.                sort(d,d+p-1,cmp);    
  91.                cout.setf(ios::fixed);//保留两位小数    
  92.                cout.precision(2);    
  93.                cout<<d[s-1]<<endl;    
  94.          }    
  95.     return 0;    
  96. }    
    #include <iostream>  
    #include<cstdio>  
    #include<cstring>  
    #include<cmath>  
    #include<algorithm>  
    using namespace std;  
    int flag1=0;  
    int n,s,p;  
    double sum;  
    double arr_list[504][504];  
    double d[503];  
    struct Edge  
    {  
         int point;  
         double lowcost;  
         int flag;  
    };  
    Edge edge[505];  
    bool cmp(double a,double b)  
    {  
         return a>b;  
    }  
    struct Point  
    {  
         double x,y;  
    }point[502];  
    void prim(int p)  
    {  
         int i,j,k=1;  
         double min,sum2=0;  
         j=1;  
         for(i=1;i<=p;i++)  
         {  
              if(i!=j)  
              {  
                   edge[i].point=j;  
                   edge[i].lowcost=arr_list[j][i];  
                   edge[i].flag=0;  
              }  
         }  
         edge[j].lowcost=0;  
         edge[j].flag=1;  
         int l=0;  
         for(i=1;i<p;i++)  
         {  
              min=65535000;  
              for(j=2;j<=p;j++)  
              {  
                   if(edge[j].flag==0&&edge[j].lowcost<min)  
                   {  
                        k=j;  
                        min=edge[j].lowcost;  
                   }  
              }  
              d[l++]=arr_list[k][edge[k].point];  
              //sum2+=min;  
              edge[k].flag=1;  
              for(j=2;j<=p;j++)  
              {  
                   if(edge[j].flag==0&&arr_list[k][j]<edge[j].lowcost)  
                   {  
                        edge[j].point=k;  
                        edge[j].lowcost=arr_list[k][j];  
                   }  
              }  
         }  
    }  
    int main()  
    {  
          //  freopen("cin.txt","r",stdin);  
             cin>>n;  
             while(n--)  
             {  
                   cin>>s>>p;  
                   for(int i=1;i<=p;i++)  
                   {  
                        cin>>point[i].x>>point[i].y;  
                        arr_list[i][i]=65535000;  
                   }  
                   for(int i=1;i<p;i++)  
                   {  
                        for(int j=i+1;j<=p;j++)  
                        {  
                             arr_list[i][j]=sqrt(pow((point[i].x-point[j].x),2)+pow((point[i].y-point[j].y),2));  
                             arr_list[j][i]=arr_list[i][j];  
                       //cout<<arr_list[i][j]<<endl;  
                        }  
                   }  
                   prim(p);  
                   sort(d,d+p-1,cmp);  
                   cout.setf(ios::fixed);//保留两位小数  
                   cout.precision(2);  
                   cout<<d[s-1]<<endl;  
             }  
        return 0;  
    }  

4、多源点单汇点 之前都是单源最短路,如果是多源单汇点的话也是一样的

hdu2680Choose the best route dijkstra

  1. #include <iostream>    
  2. #include<cstdio>    
  3. #include<cstring>    
  4. #define MaxN 10010    
  5. #define MaxInt 2000000    
  6. using namespace std;    
  7. int map[MaxN][MaxN],dist[MaxN],start;    
  8. bool mark[MaxN];    
  9. int n,m,s,p,q,t,w,b,end,min1,minn,ww;    
  10. void dijkstra(int s)    
  11. {    
  12.      memset(mark,0,sizeof(mark));    
  13.      for(int i=1;i<=n;i++) dist[i]=map[s][i];    
  14.      mark[s]=1;dist[s]=0;    
  15.      int k;    
  16.      for(int i=1;i<n;i++)    
  17.      {    
  18.           minn=MaxInt;    
  19.           for(int j=1;j<=n;j++)    
  20.           {    
  21.                if(!mark[j]&&minn>dist[j])    
  22.                {    
  23.                     k=j;    
  24.                     minn=dist[j];    
  25.                }    
  26.           }    
  27.           if(minn==MaxInt) break;    
  28.           mark[k]=1;    
  29.           for(int j=1;j<=n;j++)    
  30.           {    
  31.                if(!mark[j]&&dist[j]>dist[k]+map[k][j])    
  32.                {    
  33.                     dist[j]=dist[k]+map[k][j];    
  34.                }    
  35.           }    
  36.      }    
  37. }    
  38. int main()    
  39. {    
  40.    // freopen("cin.txt","r",stdin);    
  41.     while(~scanf("%d%d%d",&n,&m,&s))    
  42.     {    
  43.          for(int i=1;i<=n;i++)    
  44.          {    
  45.               for(int j=1;j<=n;j++)    
  46.               {    
  47.                    map[i][j]=MaxInt;    
  48.               }    
  49.          }    
  50.          for(int i=0;i<m;i++)    
  51.          {    
  52.               scanf("%d%d%d",&p,&q,&t);    
  53.               if(t<map[q][p])    
  54.               map[q][p]=t;    
  55.          }    
  56.          dijkstra(s);    
  57.          min1=MaxInt;    
  58.          scanf("%d",&w);    
  59.          while(w--)    
  60.          {    
  61.               scanf("%d",&ww);    
  62.               if(min1>dist[ww]) min1=dist[ww];    
  63.          }    
  64.          if(min1!=MaxInt)    
  65.          printf("%d\n",min1);    
  66.          else printf("-1\n");    
  67.     }    
  68.     return 0;    
  69. }    
    #include <iostream>  
    #include<cstdio>  
    #include<cstring>  
    #define MaxN 10010  
    #define MaxInt 2000000  
    using namespace std;  
    int map[MaxN][MaxN],dist[MaxN],start;  
    bool mark[MaxN];  
    int n,m,s,p,q,t,w,b,end,min1,minn,ww;  
    void dijkstra(int s)  
    {  
         memset(mark,0,sizeof(mark));  
         for(int i=1;i<=n;i++) dist[i]=map[s][i];  
         mark[s]=1;dist[s]=0;  
         int k;  
         for(int i=1;i<n;i++)  
         {  
              minn=MaxInt;  
              for(int j=1;j<=n;j++)  
              {  
                   if(!mark[j]&&minn>dist[j])  
                   {  
                        k=j;  
                        minn=dist[j];  
                   }  
              }  
              if(minn==MaxInt) break;  
              mark[k]=1;  
              for(int j=1;j<=n;j++)  
              {  
                   if(!mark[j]&&dist[j]>dist[k]+map[k][j])  
                   {  
                        dist[j]=dist[k]+map[k][j];  
                   }  
              }  
         }  
    }  
    int main()  
    {  
       // freopen("cin.txt","r",stdin);  
        while(~scanf("%d%d%d",&n,&m,&s))  
        {  
             for(int i=1;i<=n;i++)  
             {  
                  for(int j=1;j<=n;j++)  
                  {  
                       map[i][j]=MaxInt;  
                  }  
             }  
             for(int i=0;i<m;i++)  
             {  
                  scanf("%d%d%d",&p,&q,&t);  
                  if(t<map[q][p])  
                  map[q][p]=t;  
             }  
             dijkstra(s);  
             min1=MaxInt;  
             scanf("%d",&w);  
             while(w--)  
             {  
                  scanf("%d",&ww);  
                  if(min1>dist[ww]) min1=dist[ww];  
             }  
             if(min1!=MaxInt)  
             printf("%d\n",min1);  
             else printf("-1\n");  
        }  
        return 0;  
    }  

5、限定必须连上给定的两点 这是一个关于最小生成树的原理应用,也是以签到题的姿态出现的区域赛题

HDU 4463 Outlets 最小生成树Kr~

既然要求他俩必须先连,那就先连上,逐渐选择最小的边加入边集中就ok啦

  1. #include<iostream>    
  2. #include<cstring>    
  3. #include<cstdio>    
  4. #include<cmath>    
  5. #include<algorithm>    
  6. using namespace std;    
  7. const int maxn=60*60;    
  8. struct point    
  9. {    
  10.     int x,y;    
  11.     double dis;    
  12.     point(){}    
  13.     point(int _x,int _y,double _d):x(_x),y(_y),dis(_d){}    
  14.     bool operator <(const struct point &tmp)const{    
  15.         return this->dis<tmp.dis;    
  16.     }    
  17. }p[maxn];    
  18. point pp[100];    
  19. int par[60];    
  20. void init(){    
  21.     for(int i=0;i<60;i++) par[i]=i;    
  22. }    
  23. int find_par(int x){    
  24.     if(x!=par[x]) return par[x]=find_par(par[x]);    
  25.     return par[x];    
  26. }    
  27. bool Union(int x,int y){    
  28.     x=find_par(x);    
  29.     y=find_par(y);    
  30.     if(x!=y){    
  31.         par[y]=x;    
  32.         return true;    
  33.     }    
  34.     return false;    
  35. }    
  36. double calu(point a,point b){    
  37.     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));    
  38. }    
  39. int main()    
  40. {    
  41.    // freopen("cin.txt","r",stdin);    
  42.     int n,p1,q1;    
  43.     while(~scanf("%d",&n)&&n)    
  44.     {    
  45.         init();    
  46.         scanf("%d%d",&p1,&q1);    
  47.         int cnt=0;    
  48.         for(int i=1;i<=n;i++)    
  49.         {    
  50.             int x,y;    
  51.             scanf("%d%d",&pp[i].x,&pp[i].y);    
  52.             for(int j=1;j<i;j++)    
  53.             {    
  54.                 double d=calu(pp[i],pp[j]);    
  55.                 p[cnt++]=point(i,j,d);    
  56.             }    
  57.         }    
  58.         double ans=0;    
  59.         Union(p1,q1);    
  60.         ans+=calu(pp[p1],pp[q1]);    
  61.         sort(p,p+cnt);    
  62.         for(int i=0;i<cnt;i++)    
  63.         {    
  64.             if(Union(p[i].x,p[i].y))    
  65.              ans+=p[i].dis;    
  66.         }    
  67.         printf("%.2lf\n",ans);    
  68.     }    
  69. }    
    #include<iostream>  
    #include<cstring>  
    #include<cstdio>  
    #include<cmath>  
    #include<algorithm>  
    using namespace std;  
    const int maxn=60*60;  
    struct point  
    {  
        int x,y;  
        double dis;  
        point(){}  
        point(int _x,int _y,double _d):x(_x),y(_y),dis(_d){}  
        bool operator <(const struct point &tmp)const{  
            return this->dis<tmp.dis;  
        }  
    }p[maxn];  
    point pp[100];  
    int par[60];  
    void init(){  
        for(int i=0;i<60;i++) par[i]=i;  
    }  
    int find_par(int x){  
        if(x!=par[x]) return par[x]=find_par(par[x]);  
        return par[x];  
    }  
    bool Union(int x,int y){  
        x=find_par(x);  
        y=find_par(y);  
        if(x!=y){  
            par[y]=x;  
            return true;  
        }  
        return false;  
    }  
    double calu(point a,point b){  
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));  
    }  
    int main()  
    {  
       // freopen("cin.txt","r",stdin);  
        int n,p1,q1;  
        while(~scanf("%d",&n)&&n)  
        {  
            init();  
            scanf("%d%d",&p1,&q1);  
            int cnt=0;  
            for(int i=1;i<=n;i++)  
            {  
                int x,y;  
                scanf("%d%d",&pp[i].x,&pp[i].y);  
                for(int j=1;j<i;j++)  
                {  
                    double d=calu(pp[i],pp[j]);  
                    p[cnt++]=point(i,j,d);  
                }  
            }  
            double ans=0;  
            Union(p1,q1);  
            ans+=calu(pp[p1],pp[q1]);  
            sort(p,p+cnt);  
            for(int i=0;i<cnt;i++)  
            {  
                if(Union(p[i].x,p[i].y))  
                 ans+=p[i].dis;  
            }  
            printf("%.2lf\n",ans);  
        }  
    }  
6、floyd最小环 裸题 前一个是输出路径

poj1734Sightseeing trip floyd最小环

hdu1599 find the mincost route 

  1. #include<iostream>  
  2. #include<cstring>  
  3. #include<cstdlib>  
  4. #include<queue>  
  5. #include<cstdio>  
  6. #include<climits>  
  7. #include<algorithm>  
  8. using namespace std;  
  9.   
  10. const int N=111;  
  11. const int INF=0xffffff;  
  12.   
  13. int min_loop;  
  14. int num;  
  15. int map[N][N],dist[N][N],pre[N][N];  
  16. int path[N];  
  17. int n,m;  
  18.   
  19. void dfs(int i,int j)  
  20. {  
  21.     int k=pre[i][j];  
  22.     if(k==0)  
  23.     {  
  24.         path[num++]=j;  
  25.         return;  
  26.     }  
  27.     dfs(i,k);  
  28.     dfs(k,j);  
  29. }  
  30.   
  31. void Floyd()  
  32. {  
  33.     min_loop=INF;  
  34.     memset(pre,0,sizeof(pre));  
  35.     for(int k=1; k<=n; k++)  
  36.     {  
  37.         for(int i=1; i<k; i++)  
  38.         {  
  39.             for(int j=i+1; j<k; j++)  
  40.             {  
  41.                 if(dist[i][j]+map[i][k]+map[k][j]<min_loop)  
  42.                 {  
  43.                     min_loop=dist[i][j]+map[i][k]+map[k][j];  
  44.                     num=0;  
  45.                     path[num++]=i;  
  46.                     dfs(i,j);  
  47.                     path[num++]=k;  
  48.                 }  
  49.             }  
  50.         }  
  51.   
  52.         for(int i=1; i<=n; i++)  
  53.         {  
  54.             for(int j=1; j<=n; j++)  
  55.             {  
  56.                 if(dist[i][k]+dist[k][j]<dist[i][j])  
  57.                 {  
  58.                     dist[i][j]=dist[i][k]+dist[k][j];  
  59.                     pre[i][j]=k;  
  60.                 }  
  61.             }  
  62.         }  
  63.     }  
  64. }  
  65.   
  66. int main()  
  67. {  
  68.  //   freopen("cin.txt","r",stdin);  
  69.     while(~scanf("%d%d",&n,&m))  
  70.     {  
  71.         for(int i=1; i<=n; i++)  
  72.         {  
  73.             for(int j=i+1; j<=n; j++)  
  74.                 map[i][j]=map[j][i]=dist[i][j]=dist[j][i]=INF;  
  75.             map[i][i]=dist[i][i]=0;  
  76.         }  
  77.         for(int i=0; i<m; i++)  
  78.         {  
  79.             int u,v,w;  
  80.             scanf("%d%d%d",&u,&v,&w);  
  81.             if(w<map[u][v])  
  82.             {  
  83.                 map[u][v]=map[v][u]=w;  
  84.                 dist[u][v]=dist[v][u]=w;  
  85.             }  
  86.         }  
  87.         Floyd();  
  88.         if(min_loop==INF)  
  89.             puts("No solution.");  
  90.         else  
  91.         {  
  92.             for(int i=0; i<num-1; i++)  printf("%d ",path[i]);  
  93.             printf("%d\n",path[num-1]);  
  94.            //printf("%d\n",min_loop);  
  95.         }  
  96.     }  
  97.     return 0;  
  98. }  
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<cstdio>
#include<climits>
#include<algorithm>
using namespace std;

const int N=111;
const int INF=0xffffff;

int min_loop;
int num;
int map[N][N],dist[N][N],pre[N][N];
int path[N];
int n,m;

void dfs(int i,int j)
{
    int k=pre[i][j];
    if(k==0)
    {
        path[num++]=j;
        return;
    }
    dfs(i,k);
    dfs(k,j);
}

void Floyd()
{
    min_loop=INF;
    memset(pre,0,sizeof(pre));
    for(int k=1; k<=n; k++)
    {
        for(int i=1; i<k; i++)
        {
            for(int j=i+1; j<k; j++)
            {
                if(dist[i][j]+map[i][k]+map[k][j]<min_loop)
                {
                    min_loop=dist[i][j]+map[i][k]+map[k][j];
                    num=0;
                    path[num++]=i;
                    dfs(i,j);
                    path[num++]=k;
                }
            }
        }

        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                if(dist[i][k]+dist[k][j]<dist[i][j])
                {
                    dist[i][j]=dist[i][k]+dist[k][j];
                    pre[i][j]=k;
                }
            }
        }
    }
}

int main()
{
 //   freopen("cin.txt","r",stdin);
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1; i<=n; i++)
        {
            for(int j=i+1; j<=n; j++)
                map[i][j]=map[j][i]=dist[i][j]=dist[j][i]=INF;
            map[i][i]=dist[i][i]=0;
        }
        for(int i=0; i<m; i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            if(w<map[u][v])
            {
                map[u][v]=map[v][u]=w;
                dist[u][v]=dist[v][u]=w;
            }
        }
        Floyd();
        if(min_loop==INF)
            puts("No solution.");
        else
        {
            for(int i=0; i<num-1; i++)  printf("%d ",path[i]);
            printf("%d\n",path[num-1]);
           //printf("%d\n",min_loop);
        }
    }
    return 0;
}

7、单向最短路来回最短距离

POJ 3268 Silver Cow Party

虽说是来回都得求值,还记不记得之前的“孙大神的山峰序列” 一样的道理,从两边求完之后遍历数组求和最小即为答案

  1. #include<iostream>    
  2. #include<cstring>    
  3. #include<cstdlib>    
  4. #include<queue>    
  5. #include<cstdio>    
  6. using namespace std;    
  7. int n,m,x;    
  8. const int  MAXINT=0x3f3f3f3f;    
  9. const int MAXNUM=1100;    
  10. int dist[MAXNUM];    
  11. int A[MAXNUM][MAXNUM];    
  12. void Dijkstra(int v0)    
  13. {    
  14.     bool S[MAXNUM];// 判断是否已存入该点到S集合中    
  15.     for(int i=1; i<=n; ++i)    
  16.     {    
  17.         dist[i]=A[v0][i];    
  18.        // printf("%d    ",dist[i]);    
  19.         S[i]=false// 初始都未用过该点    
  20.     }    
  21.    // dist[v0] = 0;    
  22.     S[v0]=true;    
  23.     for(int i=2; i<=n; i++)    
  24.     {    
  25.         int mindist = MAXINT;    
  26.         int u = -1;// 找出当前未使用的点j的dist[j]最小值    
  27.         for(int j=1; j<=n; ++j)    
  28.         if((!S[j]) && dist[j]<mindist)    
  29.         {    
  30.             u = j;// u保存当前邻接点中距离最小的点的号码    
  31.             mindist = dist[j];    
  32.             //printf("%d        ",mindist);    
  33.         }    
  34.         S[u] = true;    
  35.         for(int j=1; j<=n; j++)    
  36.             if((!S[j]) && A[u][j]<MAXINT)    
  37.             {    
  38.                 if(dist[u] + A[u][j] < dist[j])     //在通过新加入的u点路径找到离v0点更短的路径    
  39.                 {    
  40.                     dist[j] = dist[u] + A[u][j];    //更新dis                    //记录前驱顶点    
  41.                 }    
  42.             }    
  43.     }    
  44.     return;    
  45. }    
  46. int main()    
  47. {    
  48.     //freopen("cin.txt","r",stdin);    
  49.     while(~scanf("%d%d%d",&n,&m,&x))    
  50.     {    
  51.         for(int i=1; i<=n; i++)    
  52.         {    
  53.             for(int j=i+1; j<=n; j++)    
  54.                 A[i][j]=A[j][i]=MAXINT;    
  55.         }    
  56.         for(int i=0; i<m; i++)    
  57.         {    
  58.             int u,v,w;    
  59.             scanf("%d%d%d",&u,&v,&w);    
  60.             A[u][v]=w;    
  61.             //printf("%d %d %d\n",u,v,A[u][v]);    
  62.         }    
  63.         Dijkstra(x);    
  64.         int a1[MAXNUM],a2[MAXNUM];    
  65.         for(int i=1;i<=n;i++) a1[i]=dist[i];//printf("%d ",a1[i]);    
  66.        // puts("");    
  67.         for(int i=1;i<=n;i++)    
  68.             for(int j=i+1;j<=n;j++)    
  69.             {    
  70.                 int tmp;    
  71.                 tmp=A[i][j];    
  72.                 A[i][j]=A[j][i];    
  73.                 A[j][i]=tmp;    
  74.             }    
  75.         Dijkstra(x);    
  76.         for(int i=1;i<=n;i++) a2[i]=dist[i];    
  77.         int minn=0;    
  78.         for(int i=1;i<=n;i++)    
  79.         {    
  80.             minn=max(minn,a1[i]+a2[i]);    
  81.         }    
  82.         printf("%d\n",minn);    
  83.     }    
  84.     return 0;    
  85. }    
    #include<iostream>  
    #include<cstring>  
    #include<cstdlib>  
    #include<queue>  
    #include<cstdio>  
    using namespace std;  
    int n,m,x;  
    const int  MAXINT=0x3f3f3f3f;  
    const int MAXNUM=1100;  
    int dist[MAXNUM];  
    int A[MAXNUM][MAXNUM];  
    void Dijkstra(int v0)  
    {  
        bool S[MAXNUM];// 判断是否已存入该点到S集合中  
        for(int i=1; i<=n; ++i)  
        {  
            dist[i]=A[v0][i];  
           // printf("%d    ",dist[i]);  
            S[i]=false; // 初始都未用过该点  
        }  
       // dist[v0] = 0;  
        S[v0]=true;  
        for(int i=2; i<=n; i++)  
        {  
            int mindist = MAXINT;  
            int u = -1;// 找出当前未使用的点j的dist[j]最小值  
            for(int j=1; j<=n; ++j)  
            if((!S[j]) && dist[j]<mindist)  
            {  
                u = j;// u保存当前邻接点中距离最小的点的号码  
                mindist = dist[j];  
                //printf("%d        ",mindist);  
            }  
            S[u] = true;  
            for(int j=1; j<=n; j++)  
                if((!S[j]) && A[u][j]<MAXINT)  
                {  
                    if(dist[u] + A[u][j] < dist[j])     //在通过新加入的u点路径找到离v0点更短的路径  
                    {  
                        dist[j] = dist[u] + A[u][j];    //更新dis                    //记录前驱顶点  
                    }  
                }  
        }  
        return;  
    }  
    int main()  
    {  
        //freopen("cin.txt","r",stdin);  
        while(~scanf("%d%d%d",&n,&m,&x))  
        {  
            for(int i=1; i<=n; i++)  
            {  
                for(int j=i+1; j<=n; j++)  
                    A[i][j]=A[j][i]=MAXINT;  
            }  
            for(int i=0; i<m; i++)  
            {  
                int u,v,w;  
                scanf("%d%d%d",&u,&v,&w);  
                A[u][v]=w;  
                //printf("%d %d %d\n",u,v,A[u][v]);  
            }  
            Dijkstra(x);  
            int a1[MAXNUM],a2[MAXNUM];  
            for(int i=1;i<=n;i++) a1[i]=dist[i];//printf("%d ",a1[i]);  
           // puts("");  
            for(int i=1;i<=n;i++)  
                for(int j=i+1;j<=n;j++)  
                {  
                    int tmp;  
                    tmp=A[i][j];  
                    A[i][j]=A[j][i];  
                    A[j][i]=tmp;  
                }  
            Dijkstra(x);  
            for(int i=1;i<=n;i++) a2[i]=dist[i];  
            int minn=0;  
            for(int i=1;i<=n;i++)  
            {  
                minn=max(minn,a1[i]+a2[i]);  
            }  
            printf("%d\n",minn);  
        }  
        return 0;  
    }  

8、换货币,给出汇率,问是否可以通过一系列的折腾使得手中的钱增多,其实也不容想到是用floyd最短路的方法写==    dist[i][i]>1.0即为钱数增加

POJ 2240 Arbitrage floyd

  1. #include <iostream>    
  2. #include <cstdio>    
  3. #include<map>    
  4. #include <string.h>    
  5. using namespace std;    
  6. map<string,int>mat;    
  7. double dist[100][100];    
  8. int n,m;    
  9. void Floyd()    
  10. {    
  11.      for(int k=1;k<=n;k++)    
  12.         for(int i=1; i<=n; i++)    
  13.         {    
  14.             for(int j=1; j<=n; j++)    
  15.             {    
  16.                 if(dist[i][k]*dist[k][j]>dist[i][j])    
  17.                 {    
  18.                     dist[i][j]=dist[i][k]*dist[k][j];    
  19.                    // pre[i][j]=k;    
  20.                 }    
  21.             }    
  22.         }    
  23.     
  24. }    
  25. int main()    
  26. {    
  27.    // freopen("cin.txt","r",stdin);    
  28.     map<string,int>mat;    
  29.     int cnt=0;    
  30.     double w;    
  31.     string str,str1,str2;    
  32.     while(~scanf("%d",&n)&&n)    
  33.     {    
  34.         //mat.clear();    
  35.         for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)    
  36.         {    
  37.             if(i==j) dist[i][j]=1;    
  38.             else dist[i][j]=0;    
  39.         }    
  40.         for(int i=1;i<=n;i++) cin>>str,mat[str]=i;    
  41.         cin>>m;    
  42.         while(m--)    
  43.         {    
  44.             cin>>str1>>w>>str2;    
  45.             dist[mat[str1]][mat[str2]]=w;    
  46.             //maap[mat[str1]][mat[str2]]=w;    
  47.         }    
  48.         Floyd();    
  49.         printf("Case %d:",++cnt);    
  50.         bool flag=false;    
  51.         for(int i=1;i<=n;i++)    
  52.             if(dist[i][i]>1.0)    
  53.             {    
  54.                 flag=true;    
  55.                 break;    
  56.             }    
  57.         if(!flag) printf(" No\n");    
  58.         else printf(" Yes\n");    
  59.     }    
  60.     return 0;    
  61. }    
    #include <iostream>  
    #include <cstdio>  
    #include<map>  
    #include <string.h>  
    using namespace std;  
    map<string,int>mat;  
    double dist[100][100];  
    int n,m;  
    void Floyd()  
    {  
         for(int k=1;k<=n;k++)  
            for(int i=1; i<=n; i++)  
            {  
                for(int j=1; j<=n; j++)  
                {  
                    if(dist[i][k]*dist[k][j]>dist[i][j])  
                    {  
                        dist[i][j]=dist[i][k]*dist[k][j];  
                       // pre[i][j]=k;  
                    }  
                }  
            }  
      
    }  
    int main()  
    {  
       // freopen("cin.txt","r",stdin);  
        map<string,int>mat;  
        int cnt=0;  
        double w;  
        string str,str1,str2;  
        while(~scanf("%d",&n)&&n)  
        {  
            //mat.clear();  
            for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)  
            {  
                if(i==j) dist[i][j]=1;  
                else dist[i][j]=0;  
            }  
            for(int i=1;i<=n;i++) cin>>str,mat[str]=i;  
            cin>>m;  
            while(m--)  
            {  
                cin>>str1>>w>>str2;  
                dist[mat[str1]][mat[str2]]=w;  
                //maap[mat[str1]][mat[str2]]=w;  
            }  
            Floyd();  
            printf("Case %d:",++cnt);  
            bool flag=false;  
            for(int i=1;i<=n;i++)  
                if(dist[i][i]>1.0)  
                {  
                    flag=true;  
                    break;  
                }  
            if(!flag) printf(" No\n");  
            else printf(" Yes\n");  
        }  
        return 0;  
    }  

9、换货币,给出汇率和手续费,问是否可以使得手里钱增加 spfa

POJ 1860 Currency Exchange spfa  

同样是换货币,之前的题是只有汇率,这个题还有手续费,spfa  bellman都可做,我当时用的前者。为什么要用这两个方法,因为要判断"负环",当然了这个题存在“钱无限增加”的情况就说明松弛操作可以进行很多次,就是正常函数返回-1的情况==

  1. #include <iostream>    
  2. #include <cstdio>    
  3. #include <cmath>    
  4. #include <queue>    
  5. #include <string.h>    
  6. using namespace std;    
  7.     
  8. const int INF=0x3f3f3f3f;    
  9. const int maxm=511111;    
  10. const int maxn=111111;    
  11.     
  12. struct EdgeNode    
  13. {    
  14.     int to;    
  15.     int next;    
  16.     double rate,comm,w;    
  17. };    
  18. int cont[maxn];    
  19. EdgeNode edges[maxm];    
  20. int N,M,s;    
  21. double val;    
  22. int head[maxn],edge;    
  23. bool vis[maxn];    
  24. queue <int> que;    
  25. double dis[maxn];    
  26.     
  27. void addedge(int u,int v,double r,double c)    
  28. {    
  29.     edges[edge].comm=c,edges[edge].to=v;    
  30.     edges[edge].next=head[u];edges[edge].w=0;    
  31.     edges[edge].rate=r;head[u]=edge++;    
  32. }    
  33.     
  34. void init()    
  35. {    
  36.     memset(head,-1,sizeof(head));    
  37.     edge=0;    
  38.     memset(cont,0,sizeof(cont));    
  39.     memset(vis,false,sizeof(vis));    
  40.     for (int i=0; i<N; i++)    
  41.         dis[i]=0;    
  42. }    
  43.     
  44. int spfa(int s,int n)//单源最短路(s为起点,n为节点总数)///    
  45. {    
  46.     int u;    
  47.     
  48.         
  49.     while (!que.empty()) que.pop();    
  50.     
  51.     vis[s]=true;    
  52.     dis[s]=val;    
  53.     ++cont[s];    
  54.     que.push(s);    
  55.     while (!que.empty())    
  56.     {    
  57.         u=que.front();    
  58.         que.pop();    
  59.         vis[u]=false;    
  60.         for (int i=head[u]; i!=-1; i=edges[i].next)    
  61.         {    
  62.             int v=edges[i].to;    
  63.             edges[i].w=(dis[u]-edges[i].comm)*edges[i].rate-dis[u];    
  64.             if (dis[v]<dis[u]+edges[i].w)///    
  65.             {    
  66.                 dis[v]=dis[u]+edges[i].w;    
  67.                 if (!vis[v])    
  68.                 {    
  69.                     vis[v]=true;    
  70.                     que.push(v);    
  71.                 }    
  72.                 if(++cont[v]>n)    
  73.                 return -1;    
  74.             }    
  75.         }    
  76.     }    
  77.     return 1;    
  78. }    
  79.     
  80. int main()    
  81. {    
  82.    // freopen("cin.txt","r",stdin);    
  83.     while(~scanf("%d%d%d%lf",&N,&M,&s,&val))    
  84.     {    
  85.         int a,b;    
  86.         init();    
  87.         double rab,cab,rba,cba;    
  88.         while(M--)    
  89.         {    
  90.             scanf("%d%d%lf%lf%lf%lf",&a,&b,&rab,&cab,&rba,&cba);    
  91.             addedge(a,b,rab,cab);    
  92.             addedge(b,a,rba,cba);    
  93.     
  94.         }    
  95.         if(spfa(s,N)==-1)printf("YES\n");    
  96.         else printf("NO\n");    
  97.     }    
  98.     return 0;    
  99. }    
    #include <iostream>  
    #include <cstdio>  
    #include <cmath>  
    #include <queue>  
    #include <string.h>  
    using namespace std;  
      
    const int INF=0x3f3f3f3f;  
    const int maxm=511111;  
    const int maxn=111111;  
      
    struct EdgeNode  
    {  
        int to;  
        int next;  
        double rate,comm,w;  
    };  
    int cont[maxn];  
    EdgeNode edges[maxm];  
    int N,M,s;  
    double val;  
    int head[maxn],edge;  
    bool vis[maxn];  
    queue <int> que;  
    double dis[maxn];  
      
    void addedge(int u,int v,double r,double c)  
    {  
        edges[edge].comm=c,edges[edge].to=v;  
        edges[edge].next=head[u];edges[edge].w=0;  
        edges[edge].rate=r;head[u]=edge++;  
    }  
      
    void init()  
    {  
        memset(head,-1,sizeof(head));  
        edge=0;  
        memset(cont,0,sizeof(cont));  
        memset(vis,false,sizeof(vis));  
        for (int i=0; i<N; i++)  
            dis[i]=0;  
    }  
      
    int spfa(int s,int n)//单源最短路(s为起点,n为节点总数)///  
    {  
        int u;  
      
          
        while (!que.empty()) que.pop();  
      
        vis[s]=true;  
        dis[s]=val;  
        ++cont[s];  
        que.push(s);  
        while (!que.empty())  
        {  
            u=que.front();  
            que.pop();  
            vis[u]=false;  
            for (int i=head[u]; i!=-1; i=edges[i].next)  
            {  
                int v=edges[i].to;  
                edges[i].w=(dis[u]-edges[i].comm)*edges[i].rate-dis[u];  
                if (dis[v]<dis[u]+edges[i].w)///  
                {  
                    dis[v]=dis[u]+edges[i].w;  
                    if (!vis[v])  
                    {  
                        vis[v]=true;  
                        que.push(v);  
                    }  
                    if(++cont[v]>n)  
                    return -1;  
                }  
            }  
        }  
        return 1;  
    }  
      
    int main()  
    {  
       // freopen("cin.txt","r",stdin);  
        while(~scanf("%d%d%d%lf",&N,&M,&s,&val))  
        {  
            int a,b;  
            init();  
            double rab,cab,rba,cba;  
            while(M--)  
            {  
                scanf("%d%d%lf%lf%lf%lf",&a,&b,&rab,&cab,&rba,&cba);  
                addedge(a,b,rab,cab);  
                addedge(b,a,rba,cba);  
      
            }  
            if(spfa(s,N)==-1)printf("YES\n");  
            else printf("NO\n");  
        }  
        return 0;  
    }  

10、差分约束入门题 分糖果“小于等于”  by the way 小于等于是最短路 大于等于是最长路

POJ 3159 Candies差分约束系统 spfa

核心在于:xj-xi<=bk,会发现它类似最短路中的三角不等式d[v]<=d[u]+w[u,v],即d[v]-d[u]<=w[u,v]

  1. #include <iostream>    
  2. #include <cstdio>    
  3. #include <cstring>    
  4. using namespace std;    
  5. const int maxn=30005;    
  6. int dis[maxn],head[maxn];    
  7. int n,m,sum;    
  8. bool vis[maxn];    
  9. struct node{    
  10.     int v,w,next;    
  11. }edge[150010];    
  12. void addedge(int a,int b,int c){    
  13.     edge[sum].v=b;    
  14.     edge[sum].w=c;    
  15.     edge[sum].next=head[a];    
  16.     head[a]=sum++;    
  17. }    
  18. bool spfa(int s){    
  19.     int stack[maxn],outque[maxn],top=0;    
  20.     memset(dis,0x3f,sizeof(dis));    
  21.     memset(vis,0,sizeof(vis));    
  22.     memset(outque,0,sizeof(outque));    
  23.     stack[top++]=s;    
  24.     vis[s]=1;//vis数组的作用不是判断它是否被更新过 而是是否在栈里!    
  25.     dis[s]=0;    
  26.     while(top){    
  27.         int tmp=stack[--top];    
  28.         vis[tmp]=0;    
  29.         outque[tmp]++;    
  30.         if(outque[tmp]>n)  return 0;  //判断负环,当然这里没有必要写它    
  31.         int k=head[tmp];    
  32.         while(k>-1){    
  33.              if(dis[edge[k].v]>edge[k].w+dis[tmp]){    
  34.                   dis[edge[k].v]=edge[k].w+dis[tmp];    
  35.                   if(vis[edge[k].v]==0){    
  36.                        vis[edge[k].v]=1;    
  37.                        stack[top++]=edge[k].v;    
  38.                   }    
  39.              }    
  40.              k=edge[k].next;    
  41.         }    
  42.     }    
  43.     return 1;    
  44. }    
  45. int main()    
  46. {    
  47.     //freopen("cin.txt","r",stdin);    
  48.     while(cin>>n>>m){    
  49.         sum=0;    
  50.         memset(head,-1,sizeof(head));    
  51.         int a,b,c;    
  52.         while(m--){    
  53.             scanf("%d%d%d",&a,&b,&c);    
  54.             addedge(a,b,c);    
  55.         }    
  56.         spfa(1);    
  57.         printf("%d\n",dis[n]);    
  58.     }    
  59.     return 0;    
  60. }    
    #include <iostream>  
    #include <cstdio>  
    #include <cstring>  
    using namespace std;  
    const int maxn=30005;  
    int dis[maxn],head[maxn];  
    int n,m,sum;  
    bool vis[maxn];  
    struct node{  
        int v,w,next;  
    }edge[150010];  
    void addedge(int a,int b,int c){  
        edge[sum].v=b;  
        edge[sum].w=c;  
        edge[sum].next=head[a];  
        head[a]=sum++;  
    }  
    bool spfa(int s){  
        int stack[maxn],outque[maxn],top=0;  
        memset(dis,0x3f,sizeof(dis));  
        memset(vis,0,sizeof(vis));  
        memset(outque,0,sizeof(outque));  
        stack[top++]=s;  
        vis[s]=1;//vis数组的作用不是判断它是否被更新过 而是是否在栈里!  
        dis[s]=0;  
        while(top){  
            int tmp=stack[--top];  
            vis[tmp]=0;  
            outque[tmp]++;  
            if(outque[tmp]>n)  return 0;  //判断负环,当然这里没有必要写它  
            int k=head[tmp];  
            while(k>-1){  
                 if(dis[edge[k].v]>edge[k].w+dis[tmp]){  
                      dis[edge[k].v]=edge[k].w+dis[tmp];  
                      if(vis[edge[k].v]==0){  
                           vis[edge[k].v]=1;  
                           stack[top++]=edge[k].v;  
                      }  
                 }  
                 k=edge[k].next;  
            }  
        }  
        return 1;  
    }  
    int main()  
    {  
        //freopen("cin.txt","r",stdin);  
        while(cin>>n>>m){  
            sum=0;  
            memset(head,-1,sizeof(head));  
            int a,b,c;  
            while(m--){  
                scanf("%d%d%d",&a,&b,&c);  
                addedge(a,b,c);  
            }  
            spfa(1);  
            printf("%d\n",dis[n]);  
        }  
        return 0;  
    }  

11、差分约束系统论文题

zoj1420Cashier Employment

题意:每天每个时间有一定的收银员人数需求(以小时为单位)另有很多人应聘,一旦应聘,干满8小时,问最少雇佣多少人

s[]数组表示共雇佣了的人数,num[] 当前时刻最多可雇佣人数,r[]某时刻的最少人数。1. s[i]-s[i-1]>=0 2. s[i-1]-s[i]>=-num[i]  (1<=i<=24)  3. s[i]-s[i-8]>=r[i](8<=i<=24) 4. s[i]-s[i+16]>=r[i]-ans  (1<=i<=8)   5.  s[24]-s[0]>=ans                      注意第4个式子,是将第3个式子扩展到"每天"得到的

  1. #include <iostream>    
  2. #include<cstdio>    
  3. #include<cstring>    
  4. #include<vector>    
  5. #include<queue>    
  6. using namespace std;    
  7. const int inf=0x3f3f3f3f;    
  8. const int maxn=50005;    
  9. struct Edge    
  10. {    
  11.     int v,cost;    
  12.     Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}    
  13. };    
  14. vector<Edge>E[maxn];    
  15. void addedge(int u,int v,int w)    
  16. {    
  17.     E[u].push_back(Edge(v,w));    
  18. }    
  19. bool vis[maxn];    
  20. int cnt[maxn];    
  21. int dist[maxn];    
  22. bool spfa(int start,int n)    
  23. {    
  24.     memset(vis,false,sizeof(vis));    
  25.     memset(dist,-inf,sizeof(dist));    
  26.     vis[start]=true;    
  27.     dist[start]=0;    
  28.     queue<int>que;    
  29.     while(!que.empty()) que.pop();    
  30.     que.push(start);    
  31.     memset(cnt,0,sizeof(cnt));    
  32.     cnt[start]=1;    
  33.     while(!que.empty())    
  34.     {    
  35.         int u=que.front();    
  36.         que.pop();    
  37.         vis[u]=false;    
  38.         for(int i=0;i<E[u].size();i++)    
  39.         {    
  40.             int v=E[u][i].v;    
  41.             if(dist[v]<dist[u]+E[u][i].cost)    
  42.             {    
  43.                 dist[v]=dist[u]+E[u][i].cost;    
  44.                 if(!vis[v])    
  45.                 {    
  46.                     vis[v]=true;    
  47.                     que.push(v);    
  48.                     if(++cnt[v]>n) return false;    
  49.                 }    
  50.             }    
  51.         }    
  52.     }    
  53.     return true;    
  54. }    
  55. int num[30],r[30];    
  56. int main()    
  57. {    
  58.     //freopen("cin.txt","r",stdin);    
  59.     int t,ans,m;    
  60.     scanf("%d",&t);    
  61.     while(t--)    
  62.     {    
  63.         for(int i=1;i<=24;i++) scanf("%d",&r[i]);    
  64.         for(int i=0;i<25;i++) num[i]=0;    
  65.         scanf("%d",&m);    
  66.         for(int i=0;i<m;i++)    
  67.         {    
  68.             int tmp;    
  69.             scanf("%d",&tmp);    
  70.             num[tmp+1]++;///!!!    
  71.         }    
  72.         ans=1;    
  73.         bool flag=true;    
  74.         int l=0,right=m;    
  75.         while(l<right)    
  76.         {    
  77.             for(int i=0;i<=24;i++) E[i].clear();    
  78.             ans=(l+right)/2;    
  79.             for(int i=1;i<=24;i++)    
  80.             {    
  81.                 addedge(i-1,i,0);    
  82.                 addedge(i,i-1,-num[i]);    
  83.             }    
  84.             for(int i=8;i<=24;i++) addedge(i-8,i,r[i]);    
  85.             for(int i=1;i<=8;i++) addedge(i+16,i,r[i]-ans);    
  86.             addedge(0,24,ans);    
  87.             if(spfa(0,25)) right=ans,flag=false;    
  88.             else l=ans+1;    
  89.         }    
  90.         if(!flag) printf("%d\n",right);    
  91.         else printf("No Solution\n");    
  92.     }    
  93.     return 0;    
  94. }    
#include <iostream>  
#include<cstdio>  
#include<cstring>  
#include<vector>  
#include<queue>  
using namespace std;  
const int inf=0x3f3f3f3f;  
const int maxn=50005;  
struct Edge  
{  
    int v,cost;  
    Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}  
};  
vector<Edge>E[maxn];  
void addedge(int u,int v,int w)  
{  
    E[u].push_back(Edge(v,w));  
}  
bool vis[maxn];  
int cnt[maxn];  
int dist[maxn];  
bool spfa(int start,int n)  
{  
    memset(vis,false,sizeof(vis));  
    memset(dist,-inf,sizeof(dist));  
    vis[start]=true;  
    dist[start]=0;  
    queue<int>que;  
    while(!que.empty()) que.pop();  
    que.push(start);  
    memset(cnt,0,sizeof(cnt));  
    cnt[start]=1;  
    while(!que.empty())  
    {  
        int u=que.front();  
        que.pop();  
        vis[u]=false;  
        for(int i=0;i<E[u].size();i++)  
        {  
            int v=E[u][i].v;  
            if(dist[v]<dist[u]+E[u][i].cost)  
            {  
                dist[v]=dist[u]+E[u][i].cost;  
                if(!vis[v])  
                {  
                    vis[v]=true;  
                    que.push(v);  
                    if(++cnt[v]>n) return false;  
                }  
            }  
        }  
    }  
    return true;  
}  
int num[30],r[30];  
int main()  
{  
    //freopen("cin.txt","r",stdin);  
    int t,ans,m;  
    scanf("%d",&t);  
    while(t--)  
    {  
        for(int i=1;i<=24;i++) scanf("%d",&r[i]);  
        for(int i=0;i<25;i++) num[i]=0;  
        scanf("%d",&m);  
        for(int i=0;i<m;i++)  
        {  
            int tmp;  
            scanf("%d",&tmp);  
            num[tmp+1]++;///!!!  
        }  
        ans=1;  
        bool flag=true;  
        int l=0,right=m;  
        while(l<right)  
        {  
            for(int i=0;i<=24;i++) E[i].clear();  
            ans=(l+right)/2;  
            for(int i=1;i<=24;i++)  
            {  
                addedge(i-1,i,0);  
                addedge(i,i-1,-num[i]);  
            }  
            for(int i=8;i<=24;i++) addedge(i-8,i,r[i]);  
            for(int i=1;i<=8;i++) addedge(i+16,i,r[i]-ans);  
            addedge(0,24,ans);  
            if(spfa(0,25)) right=ans,flag=false;  
            else l=ans+1;  
        }  
        if(!flag) printf("%d\n",right);  
        else printf("No Solution\n");  
    }  
    return 0;  
}  

12、差分约束系统水题

hdu1531King

题意:给出asi+asi+1+…+asi+n大于或者小于ki  那么设从a[1]到a[i]的和为一个数,把它转化成最长路或者最短路都可做

  1. #include <iostream>    
  2. #include<cstdio>    
  3. #include<cstring>    
  4. #include<vector>    
  5. #include<queue>    
  6. using namespace std;    
  7. const int inf=0x3f3f3f3f;    
  8. const int maxn=500;    
  9. struct Edge    
  10. {    
  11.     int v,cost;    
  12.     Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}    
  13. };    
  14. vector<Edge>E[maxn];    
  15. void addedge(int u,int v,int w)    
  16. {    
  17.     E[u].push_back(Edge(v,w));    
  18. }    
  19. bool vis[maxn];    
  20. int cnt[maxn];    
  21. int dist[maxn];    
  22. bool spfa(int start,int n)    
  23. {    
  24.     memset(vis,false,sizeof(vis));    
  25.     memset(dist,-inf,sizeof(dist));    
  26.     vis[start]=true;    
  27.     dist[start]=0;    
  28.     queue<int>que;    
  29.     while(!que.empty()) que.pop();    
  30.     que.push(start);    
  31.     memset(cnt,0,sizeof(cnt));    
  32.     cnt[start]=1;    
  33.     while(!que.empty())    
  34.     {    
  35.         int u=que.front();    
  36.         que.pop();    
  37.         vis[u]=false;    
  38.         for(int i=0;i<E[u].size();i++)    
  39.         {    
  40.             int v=E[u][i].v;    
  41.             if(dist[v]<dist[u]+E[u][i].cost)    
  42.             {    
  43.                 dist[v]=dist[u]+E[u][i].cost;    
  44.                 if(!vis[v])    
  45.                 {    
  46.                     vis[v]=true;    
  47.                     que.push(v);    
  48.                     if(++cnt[v]>n) return false;    
  49.                 }    
  50.             }    
  51.         }    
  52.     }    
  53.     return true;    
  54. }    
  55. int main()    
  56. {    
  57.  //   freopen("cin.txt","r",stdin);    
  58.     int n,m,si,ni,ki;    
  59.     char oi[4];    
  60.     while(~scanf("%d",&n)&&n)    
  61.     {    
  62.         scanf("%d",&m);    
  63.         for(int i=0;i<=n+2;i++) E[i].clear();    
  64.         while(m--)    
  65.         {    
  66.             scanf("%d%d%s%d",&si,&ni,oi,&ki);    
  67.             if(oi[0]=='g') addedge(si-1,si+ni,ki+1);    
  68.             else addedge(si+ni,si-1,1-ki);    
  69.         }    
  70.         for(int i=0;i<=n;i++)addedge(n+1,i,0);    
  71.         if(spfa(n+1,n+2)) puts("lamentable kingdom");    
  72.         else puts("successful conspiracy");    
  73.     }    
  74.     return 0;    
  75. }    
    #include <iostream>  
    #include<cstdio>  
    #include<cstring>  
    #include<vector>  
    #include<queue>  
    using namespace std;  
    const int inf=0x3f3f3f3f;  
    const int maxn=500;  
    struct Edge  
    {  
        int v,cost;  
        Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}  
    };  
    vector<Edge>E[maxn];  
    void addedge(int u,int v,int w)  
    {  
        E[u].push_back(Edge(v,w));  
    }  
    bool vis[maxn];  
    int cnt[maxn];  
    int dist[maxn];  
    bool spfa(int start,int n)  
    {  
        memset(vis,false,sizeof(vis));  
        memset(dist,-inf,sizeof(dist));  
        vis[start]=true;  
        dist[start]=0;  
        queue<int>que;  
        while(!que.empty()) que.pop();  
        que.push(start);  
        memset(cnt,0,sizeof(cnt));  
        cnt[start]=1;  
        while(!que.empty())  
        {  
            int u=que.front();  
            que.pop();  
            vis[u]=false;  
            for(int i=0;i<E[u].size();i++)  
            {  
                int v=E[u][i].v;  
                if(dist[v]<dist[u]+E[u][i].cost)  
                {  
                    dist[v]=dist[u]+E[u][i].cost;  
                    if(!vis[v])  
                    {  
                        vis[v]=true;  
                        que.push(v);  
                        if(++cnt[v]>n) return false;  
                    }  
                }  
            }  
        }  
        return true;  
    }  
    int main()  
    {  
     //   freopen("cin.txt","r",stdin);  
        int n,m,si,ni,ki;  
        char oi[4];  
        while(~scanf("%d",&n)&&n)  
        {  
            scanf("%d",&m);  
            for(int i=0;i<=n+2;i++) E[i].clear();  
            while(m--)  
            {  
                scanf("%d%d%s%d",&si,&ni,oi,&ki);  
                if(oi[0]=='g') addedge(si-1,si+ni,ki+1);  
                else addedge(si+ni,si-1,1-ki);  
            }  
            for(int i=0;i<=n;i++)addedge(n+1,i,0);  
            if(spfa(n+1,n+2)) puts("lamentable kingdom");  
            else puts("successful conspiracy");  
        }  
        return 0;  
    }  

13、差分约束系统较难题 :跳房子

hdu3440House Man【差分约束系统】

题意:由左至右一堆高矮不同的小房子,只能从左向右水平距离不超过d个房子,问水平最多走多远

做法:先为存有(点序号,房子高度)的结构体数组排序,枚举相邻高度的房子,为其加"d"的边,跑最短路。注意最终求的是最左边点(起点)和最右边点(终点)

  1. #include <iostream>    
  2. #include<cstdio>    
  3. #include<cstring>    
  4. #include<vector>    
  5. #include<queue>    
  6. #include<algorithm>    
  7. using namespace std;    
  8. const int inf=0x3f3f3f3f;    
  9. const int maxn=1005;    
  10. struct Edge    
  11. {    
  12.     int v,cost;    
  13.     Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}    
  14. };    
  15. vector<Edge>E[maxn];    
  16. void addedge(int u,int v,int w)    
  17. {    
  18.     E[u].push_back(Edge(v,w));    
  19. }    
  20. bool vis[maxn];    
  21. int cnt[maxn];    
  22. int dist[maxn];    
  23. bool spfa(int start,int n)    
  24. {    
  25.     memset(vis,false,sizeof(vis));    
  26.     memset(dist,inf,sizeof(dist));    
  27.     vis[start]=true;    
  28.     dist[start]=0;    
  29.     queue<int>que;    
  30.     while(!que.empty()) que.pop();    
  31.     que.push(start);    
  32.     memset(cnt,0,sizeof(cnt));    
  33.     cnt[start]=1;    
  34.     while(!que.empty())    
  35.     {    
  36.         int u=que.front();    
  37.         que.pop();    
  38.         vis[u]=false;    
  39.         for(int i=0;i<E[u].size();i++)    
  40.         {    
  41.             int v=E[u][i].v;    
  42.             if(dist[v]>dist[u]+E[u][i].cost)    
  43.             {    
  44.                 dist[v]=dist[u]+E[u][i].cost;    
  45.                 if(!vis[v])    
  46.                 {    
  47.                     vis[v]=true;    
  48.                     que.push(v);    
  49.                     if(++cnt[v]>n) return false;    
  50.                 }    
  51.             }    
  52.         }    
  53.     }    
  54.     return true;    
  55. }    
  56. struct node    
  57. {    
  58.     int val,pos;    
  59. }nt[maxn];    
  60. bool cmp(node a,node b)    
  61. {    
  62.     return a.val<b.val;    
  63. }    
  64. int main()    
  65. {    
  66.   //  freopen("cin.txt","r",stdin);    
  67.     int t,n,d,cas=1;    
  68.     scanf("%d",&t);    
  69.     while(t--)    
  70.     {    
  71.         scanf("%d%d",&n,&d);    
  72.         for(int i=1;i<=n;i++) scanf("%d",&nt[i].val),nt[i].pos=i;    
  73.         sort(nt+1,nt+1+n,cmp);    
  74.         for(int i=0;i<=n;i++) E[i].clear();    
  75.         for(int i=1;i<n;i++)    
  76.         {    
  77.             addedge(i+1,i,-1);    
  78.             if(nt[i].pos<nt[i+1].pos)    
  79.                 addedge(nt[i].pos,nt[i+1].pos,d);    
  80.             else addedge(nt[i+1].pos,nt[i].pos,d);    
  81.         }    
  82.         printf("Case %d: ",cas++);    
  83.         int minn,maxn;    
  84.         if(nt[1].pos<nt[n].pos)minn=nt[1].pos,maxn=nt[n].pos;    
  85.         else minn=nt[n].pos,maxn=nt[1].pos;    
  86.         if(!spfa(minn,n)) printf("-1\n");    
  87.         else printf("%d\n",dist[maxn]);    
  88.     }    
  89.     return 0;    
  90. }    
    #include <iostream>  
    #include<cstdio>  
    #include<cstring>  
    #include<vector>  
    #include<queue>  
    #include<algorithm>  
    using namespace std;  
    const int inf=0x3f3f3f3f;  
    const int maxn=1005;  
    struct Edge  
    {  
        int v,cost;  
        Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}  
    };  
    vector<Edge>E[maxn];  
    void addedge(int u,int v,int w)  
    {  
        E[u].push_back(Edge(v,w));  
    }  
    bool vis[maxn];  
    int cnt[maxn];  
    int dist[maxn];  
    bool spfa(int start,int n)  
    {  
        memset(vis,false,sizeof(vis));  
        memset(dist,inf,sizeof(dist));  
        vis[start]=true;  
        dist[start]=0;  
        queue<int>que;  
        while(!que.empty()) que.pop();  
        que.push(start);  
        memset(cnt,0,sizeof(cnt));  
        cnt[start]=1;  
        while(!que.empty())  
        {  
            int u=que.front();  
            que.pop();  
            vis[u]=false;  
            for(int i=0;i<E[u].size();i++)  
            {  
                int v=E[u][i].v;  
                if(dist[v]>dist[u]+E[u][i].cost)  
                {  
                    dist[v]=dist[u]+E[u][i].cost;  
                    if(!vis[v])  
                    {  
                        vis[v]=true;  
                        que.push(v);  
                        if(++cnt[v]>n) return false;  
                    }  
                }  
            }  
        }  
        return true;  
    }  
    struct node  
    {  
        int val,pos;  
    }nt[maxn];  
    bool cmp(node a,node b)  
    {  
        return a.val<b.val;  
    }  
    int main()  
    {  
      //  freopen("cin.txt","r",stdin);  
        int t,n,d,cas=1;  
        scanf("%d",&t);  
        while(t--)  
        {  
            scanf("%d%d",&n,&d);  
            for(int i=1;i<=n;i++) scanf("%d",&nt[i].val),nt[i].pos=i;  
            sort(nt+1,nt+1+n,cmp);  
            for(int i=0;i<=n;i++) E[i].clear();  
            for(int i=1;i<n;i++)  
            {  
                addedge(i+1,i,-1);  
                if(nt[i].pos<nt[i+1].pos)  
                    addedge(nt[i].pos,nt[i+1].pos,d);  
                else addedge(nt[i+1].pos,nt[i].pos,d);  
            }  
            printf("Case %d: ",cas++);  
            int minn,maxn;  
            if(nt[1].pos<nt[n].pos)minn=nt[1].pos,maxn=nt[n].pos;  
            else minn=nt[n].pos,maxn=nt[1].pos;  
            if(!spfa(minn,n)) printf("-1\n");  
            else printf("%d\n",dist[maxn]);  
        }  
        return 0;  
    }  


14、spfa最短路+tsp状压

Hdu 4568 Hunter【spfa最短路 tsp状态压缩】

题意:n*n的矩阵,每一个格子都有相应的花费,k个宝藏的位置。从任意边界进入任意边界出去。求出得到所有宝藏的最小花费。

思路:将边界作为0点。bfs求出宝藏之间以及宝藏与0点的最短距离。一次TSP,在图中跑一次回路,从起点0回到起点,得到最小花费。

附上的也是一个 13级妹子的代码,比我的那份写的好看太多

  1. #include <iostream>    
  2. #include <cstdio>    
  3. #include <queue>    
  4. #include <cstring>    
  5. #include <algorithm>    
  6.     
  7. using namespace std;    
  8. const int INF = 0x3f3f3f3f;    
  9. int a[205][205], d[205][205];    
  10. int x[205], y[205], dp[1<<15][15];    
  11. bool v[205][205];    
  12. struct node {    
  13.     int x, y, c;    
  14.     node(int xx, int yy, int cc) {    
  15.         x = xx; y = yy; c = cc;    
  16.     }    
  17.     bool operator <(const node & A) const {    
  18.         return c > A.c;    
  19.     }    
  20. };    
  21. int dx[]={1, -1, 0, 0}, dy[]={0, 0, 1, -1};    
  22. int n, m, k;    
  23.     
  24. bool ok(int x, int y)    
  25. {    
  26.     if(x < 0 || y < 0 || x >= n || y >= m || a[x][y] == -1) {    
  27.         return false;    
  28.     }    
  29.     return true;    
  30. }    
  31.     
  32. void bfs(int s, int t)    
  33. {    
  34.     priority_queue<node> que;    
  35.     memset(v, 0, sizeof(v));    
  36.     que.push(node(x[s], y[s], 0));    
  37.     v[x[s]][y[s]] = 1;    
  38.     int c = 0;    
  39.     while(!que.empty()) {    
  40.         node e = que.top(); que.pop();    
  41.         if(e.x == x[t] && e.y == y[t]) {    
  42.             c = e.c - a[x[t]][y[t]];    
  43.         }    
  44.         for(int i = 0; i < 4; ++i) {    
  45.             int nx = e.x+dx[i], ny = e.y+dy[i];    
  46.             if(v[nx][ny] || a[nx][ny] == -1)    
  47.                 continue;    
  48.             if(nx < 0 || ny < 0 || nx >= n || ny >= m) {    
  49.     
  50.                 d[s][0] = min(d[s][0], e.c);    
  51.                 d[0][s] = min(d[0][s], e.c);    
  52.                 continue;    
  53.             }    
  54.     
  55.             v[nx][ny] = 1;    
  56.             que.push(node(nx, ny, e.c+a[nx][ny]));    
  57.         }    
  58.     }    
  59.     if(s != t) {    
  60.         d[s][t] = c;    
  61.         d[t][s] = c;    
  62.     }    
  63. }    
  64. void deal_p_p()    
  65. {    
  66.     memset(d, 0x3f, sizeof(d));    
  67.     for(int i = 1; i <= k; ++i) {    
  68.         for(int j = 1; j <= k; ++j) {    
  69.             //while(!que.empty()) que.pop();    
  70.             bfs(i, j);    
  71.         }    
  72.     }    
  73. }    
  74.     
  75. int solve()    
  76. {    
  77.     memset(dp, 0x3f, sizeof(dp));    
  78.     int nk = k+1;    
  79.     dp[(1<<nk)-1][0] = 0;    
  80.     for(int s = (1<<nk)-2; s >= 0; --s) {    
  81.         for(int v = 0; v < nk; ++v) {    
  82.             for(int u = 0; u < nk; ++u) {    
  83.                 if(!(s>>u &1)) {    
  84.                     dp[s][v] = min(dp[s][v], dp[s|1<<u][u]+d[v][u]);    
  85.                 }    
  86.             }    
  87.         }    
  88.     }    
  89.     return dp[0][0];    
  90. }    
  91.     
  92. int main()    
  93. {    
  94.     //freopen("in", "r", stdin);    
  95.     int T;    
  96.     scanf("%d", &T);    
  97.     while(T--) {    
  98.         scanf("%d%d", &n, &m);    
  99.         memset(a, 0, sizeof(a));    
  100.         for(int i = 0; i < n; ++i) {    
  101.             for(int j = 0; j < m; ++j) {    
  102.                 scanf("%d", &a[i][j]);    
  103.             }    
  104.         }    
  105.         int Sum = 0;    
  106.         scanf("%d", &k);    
  107.         memset(x, 0, sizeof(x));    
  108.         memset(y, 0, sizeof(y));    
  109.         for(int i = 1; i <= k; ++i) {    
  110.             scanf("%d%d", &x[i], &y[i]);    
  111.             Sum += a[x[i]][y[i]];    
  112.         }    
  113.         deal_p_p();    
  114.         if(k == 1) {    
  115.             if(d[1][0] == INF) {    
  116.                 printf("0\n");    
  117.             }    
  118.             else printf("%d\n", 2*d[1][0]+a[x[1]][y[1]]);    
  119.         }    
  120.         else {    
  121.             int ans = solve();    
  122.             if(ans == INF) printf("0\n");    
  123.             else printf("%d\n", ans+Sum);    
  124.         }    
  125.     }    
  126.     return 0;    
  127. }    
    #include <iostream>  
    #include <cstdio>  
    #include <queue>  
    #include <cstring>  
    #include <algorithm>  
      
    using namespace std;  
    const int INF = 0x3f3f3f3f;  
    int a[205][205], d[205][205];  
    int x[205], y[205], dp[1<<15][15];  
    bool v[205][205];  
    struct node {  
        int x, y, c;  
        node(int xx, int yy, int cc) {  
            x = xx; y = yy; c = cc;  
        }  
        bool operator <(const node & A) const {  
            return c > A.c;  
        }  
    };  
    int dx[]={1, -1, 0, 0}, dy[]={0, 0, 1, -1};  
    int n, m, k;  
      
    bool ok(int x, int y)  
    {  
        if(x < 0 || y < 0 || x >= n || y >= m || a[x][y] == -1) {  
            return false;  
        }  
        return true;  
    }  
      
    void bfs(int s, int t)  
    {  
        priority_queue<node> que;  
        memset(v, 0, sizeof(v));  
        que.push(node(x[s], y[s], 0));  
        v[x[s]][y[s]] = 1;  
        int c = 0;  
        while(!que.empty()) {  
            node e = que.top(); que.pop();  
            if(e.x == x[t] && e.y == y[t]) {  
                c = e.c - a[x[t]][y[t]];  
            }  
            for(int i = 0; i < 4; ++i) {  
                int nx = e.x+dx[i], ny = e.y+dy[i];  
                if(v[nx][ny] || a[nx][ny] == -1)  
                    continue;  
                if(nx < 0 || ny < 0 || nx >= n || ny >= m) {  
      
                    d[s][0] = min(d[s][0], e.c);  
                    d[0][s] = min(d[0][s], e.c);  
                    continue;  
                }  
      
                v[nx][ny] = 1;  
                que.push(node(nx, ny, e.c+a[nx][ny]));  
            }  
        }  
        if(s != t) {  
            d[s][t] = c;  
            d[t][s] = c;  
        }  
    }  
    void deal_p_p()  
    {  
        memset(d, 0x3f, sizeof(d));  
        for(int i = 1; i <= k; ++i) {  
            for(int j = 1; j <= k; ++j) {  
                //while(!que.empty()) que.pop();  
                bfs(i, j);  
            }  
        }  
    }  
      
    int solve()  
    {  
        memset(dp, 0x3f, sizeof(dp));  
        int nk = k+1;  
        dp[(1<<nk)-1][0] = 0;  
        for(int s = (1<<nk)-2; s >= 0; --s) {  
            for(int v = 0; v < nk; ++v) {  
                for(int u = 0; u < nk; ++u) {  
                    if(!(s>>u &1)) {  
                        dp[s][v] = min(dp[s][v], dp[s|1<<u][u]+d[v][u]);  
                    }  
                }  
            }  
        }  
        return dp[0][0];  
    }  
      
    int main()  
    {  
        //freopen("in", "r", stdin);  
        int T;  
        scanf("%d", &T);  
        while(T--) {  
            scanf("%d%d", &n, &m);  
            memset(a, 0, sizeof(a));  
            for(int i = 0; i < n; ++i) {  
                for(int j = 0; j < m; ++j) {  
                    scanf("%d", &a[i][j]);  
                }  
            }  
            int Sum = 0;  
            scanf("%d", &k);  
            memset(x, 0, sizeof(x));  
            memset(y, 0, sizeof(y));  
            for(int i = 1; i <= k; ++i) {  
                scanf("%d%d", &x[i], &y[i]);  
                Sum += a[x[i]][y[i]];  
            }  
            deal_p_p();  
            if(k == 1) {  
                if(d[1][0] == INF) {  
                    printf("0\n");  
                }  
                else printf("%d\n", 2*d[1][0]+a[x[1]][y[1]]);  
            }  
            else {  
                int ans = solve();  
                if(ans == INF) printf("0\n");  
                else printf("%d\n", ans+Sum);  
            }  
        }  
        return 0;  
    }  



15、取消一点使得最短路有最大值


hdu5137How Many Maos Does the Guanxi Worth

题意:暴发户给孩子办关系升学,需要一个人找一个人,人情钱都是这货出,你要劝说其中一个人不去帮忙使得暴发户花钱最多

枚举所有点,逐次跑最短路即可

  1. #include <iostream>    
  2.     #include<cstdio>    
  3.     #include<cstring>    
  4.     using namespace std;    
  5.     const int maxn=33;    
  6.     const int inf=0x3f3f3f3f;    
  7.     bool vis[maxn];    
  8.     int pre[maxn],lowcost[maxn],cost[maxn][maxn];    
  9.     void dijkstra(int n,int beg)    
  10.     {    
  11.         for(int i=0;i<n;i++)    
  12.         {    
  13.             lowcost[i]=inf;vis[i]=false;pre[i]=-1;    
  14.         }    
  15.         lowcost[beg]=0;    
  16.         for(int j=0;j<n;j++)    
  17.         {    
  18.             int k=-1;    
  19.             int Min=inf;    
  20.             for(int i=0;i<n;i++)    
  21.                 if(!vis[i]&&lowcost[i]<Min)    
  22.                 {    
  23.                     Min=lowcost[i];    
  24.                     k=i;    
  25.                 }    
  26.             if(k==-1)break;    
  27.             vis[k]=true;    
  28.             for(int i=0;i<n;i++)    
  29.                 if(!vis[i]&&lowcost[k]+cost[k][i]<lowcost[i])    
  30.                 {    
  31.                     lowcost[i]=lowcost[k]+cost[k][i];    
  32.                     pre[i]=k;    
  33.                 }    
  34.         }    
  35.     }    
  36.     int temp[maxn];    
  37.     int main()    
  38.     {    
  39.        // freopen("cin.txt","r",stdin);    
  40.         int n,m;    
  41.         while(~scanf("%d%d",&n,&m)&&n&&m)    
  42.         {    
  43.             memset(cost,inf,sizeof(cost));    
  44.             for(int i=0;i<m;i++)    
  45.             {    
  46.                 int a,b,c;    
  47.                 scanf("%d%d%d",&a,&b,&c);    
  48.                 a--;b--;    
  49.                 if(c>cost[a][b]) continue;    
  50.                 cost[a][b]=cost[b][a]=c;    
  51.             }    
  52.             int ans=0;    
  53.         
  54.             for(int i=1;i<n-1;i++)    
  55.             {    
  56.                 for(int j=0;j<=n-1;j++)    
  57.                 {    
  58.                     temp[j]=cost[i][j];    
  59.                     cost[i][j]=cost[j][i]=inf;    
  60.                 }    
  61.                 dijkstra(n,0);    
  62.                 if(lowcost[n-1]>ans) ans=lowcost[n-1];    
  63.                 for(int j=0;j<n;j++)    
  64.                     cost[i][j]=cost[j][i]=temp[j];    
  65.             }    
  66.             if(ans<inf) printf("%d\n",ans);    
  67.             else printf("Inf\n");    
  68.         }    
  69.         return 0;    
  70.     }    
#include <iostream>  
    #include<cstdio>  
    #include<cstring>  
    using namespace std;  
    const int maxn=33;  
    const int inf=0x3f3f3f3f;  
    bool vis[maxn];  
    int pre[maxn],lowcost[maxn],cost[maxn][maxn];  
    void dijkstra(int n,int beg)  
    {  
        for(int i=0;i<n;i++)  
        {  
            lowcost[i]=inf;vis[i]=false;pre[i]=-1;  
        }  
        lowcost[beg]=0;  
        for(int j=0;j<n;j++)  
        {  
            int k=-1;  
            int Min=inf;  
            for(int i=0;i<n;i++)  
                if(!vis[i]&&lowcost[i]<Min)  
                {  
                    Min=lowcost[i];  
                    k=i;  
                }  
            if(k==-1)break;  
            vis[k]=true;  
            for(int i=0;i<n;i++)  
                if(!vis[i]&&lowcost[k]+cost[k][i]<lowcost[i])  
                {  
                    lowcost[i]=lowcost[k]+cost[k][i];  
                    pre[i]=k;  
                }  
        }  
    }  
    int temp[maxn];  
    int main()  
    {  
       // freopen("cin.txt","r",stdin);  
        int n,m;  
        while(~scanf("%d%d",&n,&m)&&n&&m)  
        {  
            memset(cost,inf,sizeof(cost));  
            for(int i=0;i<m;i++)  
            {  
                int a,b,c;  
                scanf("%d%d%d",&a,&b,&c);  
                a--;b--;  
                if(c>cost[a][b]) continue;  
                cost[a][b]=cost[b][a]=c;  
            }  
            int ans=0;  
      
            for(int i=1;i<n-1;i++)  
            {  
                for(int j=0;j<=n-1;j++)  
                {  
                    temp[j]=cost[i][j];  
                    cost[i][j]=cost[j][i]=inf;  
                }  
                dijkstra(n,0);  
                if(lowcost[n-1]>ans) ans=lowcost[n-1];  
                for(int j=0;j<n;j++)  
                    cost[i][j]=cost[j][i]=temp[j];  
            }  
            if(ans<inf) printf("%d\n",ans);  
            else printf("Inf\n");  
        }  
        return 0;  
    }  




16、最短路反向建图(酋长是终点不是起点,最开始所有点前面再加一个源点)枚举等级区间依次跑最短路即可

poj1062昂贵的聘礼

  1. #include <iostream>    
  2. #include<cstdio>    
  3. #include<cstring>    
  4. using namespace std;    
  5. const int maxn=133;    
  6. const int inf=0x3f3f3f3f;    
  7. bool vis[maxn];    
  8. int pre[maxn],lowcost[maxn],cost[maxn][maxn],val[maxn],rank[maxn];    
  9. void dijkstra(int cost[][maxn],int n,int beg)    
  10. {    
  11.     for(int i=0;i<n;i++)    
  12.     {    
  13.         lowcost[i]=inf;vis[i]=false;pre[i]=-1;    
  14.     }    
  15.     lowcost[beg]=0;    
  16.     for(int j=0;j<n;j++)    
  17.     {    
  18.         int k=-1;    
  19.         int Min=inf;    
  20.         for(int i=0;i<n;i++)    
  21.             if(!vis[i]&&lowcost[i]<Min)    
  22.             {    
  23.                 Min=lowcost[i];    
  24.                 k=i;    
  25.             }    
  26.         if(k==-1)break;    
  27.         vis[k]=true;    
  28.         for(int i=0;i<n;i++)    
  29.             if(!vis[i]&&lowcost[k]+cost[k][i]<lowcost[i])    
  30.             {    
  31.                 lowcost[i]=lowcost[k]+cost[k][i];    
  32.                 pre[i]=k;    
  33.             }    
  34.     }    
  35. }    
  36. int tmp[maxn][maxn];    
  37. int main()    
  38. {    
  39.     freopen("cin.txt","r",stdin);    
  40.     int m,n;    
  41.     while(~scanf("%d%d",&m,&n))    
  42.     {    
  43.         memset(cost,inf,sizeof(cost));    
  44.         int maxn=0,minn=inf;    
  45.         for(int i=0;i<n;i++)    
  46.         {    
  47.             int x;    
  48.             scanf("%d%d%d",&cost[n][i],&rank[i],&x);    
  49.             if(rank[i]>maxn)maxn=rank[i];    
  50.             if(rank[i]<minn)minn=rank[i];    
  51.             while(x--)    
  52.             {    
  53.                 int t,v;    
  54.                 scanf("%d%d",&t,&v);t--;    
  55.                 if(v<cost[i][t]) cost[i][t]=v;    
  56.             }    
  57.         }    
  58.         int ans=inf;    
  59.         for(int k=max(0,rank[0]-m);k<=rank[0]+m;k++)    
  60.         {    
  61.             for(int i=0;i<n;i++)    
  62.                 for(int j=0;j<n;j++)    
  63.                 {    
  64.                     if(rank[i]>=k&&rank[i]<=k+m&&rank[j]>=k&&rank[j]<=k+m)    
  65.                         tmp[i][j]=cost[i][j];    
  66.                     else tmp[i][j]=inf;    
  67.                 }    
  68.             dijkstra(tmp,n,0);    
  69.             for(int i=0;i<n;i++)    
  70.                 if(ans>lowcost[i]+cost[n][i])    
  71.                     ans=lowcost[i]+cost[n][i];    
  72.         }    
  73.         printf("%d\n",ans);    
  74.     }    
  75.     return 0;    
  76. }    
    #include <iostream>  
    #include<cstdio>  
    #include<cstring>  
    using namespace std;  
    const int maxn=133;  
    const int inf=0x3f3f3f3f;  
    bool vis[maxn];  
    int pre[maxn],lowcost[maxn],cost[maxn][maxn],val[maxn],rank[maxn];  
    void dijkstra(int cost[][maxn],int n,int beg)  
    {  
        for(int i=0;i<n;i++)  
        {  
            lowcost[i]=inf;vis[i]=false;pre[i]=-1;  
        }  
        lowcost[beg]=0;  
        for(int j=0;j<n;j++)  
        {  
            int k=-1;  
            int Min=inf;  
            for(int i=0;i<n;i++)  
                if(!vis[i]&&lowcost[i]<Min)  
                {  
                    Min=lowcost[i];  
                    k=i;  
                }  
            if(k==-1)break;  
            vis[k]=true;  
            for(int i=0;i<n;i++)  
                if(!vis[i]&&lowcost[k]+cost[k][i]<lowcost[i])  
                {  
                    lowcost[i]=lowcost[k]+cost[k][i];  
                    pre[i]=k;  
                }  
        }  
    }  
    int tmp[maxn][maxn];  
    int main()  
    {  
        freopen("cin.txt","r",stdin);  
        int m,n;  
        while(~scanf("%d%d",&m,&n))  
        {  
            memset(cost,inf,sizeof(cost));  
            int maxn=0,minn=inf;  
            for(int i=0;i<n;i++)  
            {  
                int x;  
                scanf("%d%d%d",&cost[n][i],&rank[i],&x);  
                if(rank[i]>maxn)maxn=rank[i];  
                if(rank[i]<minn)minn=rank[i];  
                while(x--)  
                {  
                    int t,v;  
                    scanf("%d%d",&t,&v);t--;  
                    if(v<cost[i][t]) cost[i][t]=v;  
                }  
            }  
            int ans=inf;  
            for(int k=max(0,rank[0]-m);k<=rank[0]+m;k++)  
            {  
                for(int i=0;i<n;i++)  
                    for(int j=0;j<n;j++)  
                    {  
                        if(rank[i]>=k&&rank[i]<=k+m&&rank[j]>=k&&rank[j]<=k+m)  
                            tmp[i][j]=cost[i][j];  
                        else tmp[i][j]=inf;  
                    }  
                dijkstra(tmp,n,0);  
                for(int i=0;i<n;i++)  
                    if(ans>lowcost[i]+cost[n][i])  
                        ans=lowcost[i]+cost[n][i];  
            }  
            printf("%d\n",ans);  
        }  
        return 0;  
    }  

17、送餐来回的最短距离

看到这个题的时候想到上面的第7题了,然而第7题不需要每个点都遍历一遍,而这个题需要,所以这个是需要用状压的tsp的

poj3311 Hie with the Pie【floyd最短路+状态压缩】

  1. #include <iostream>    
  2. #include<cstdio>    
  3. #include<cstring>    
  4. using namespace std;    
  5. int dp[1<<11][20],n,num[11][11];    
  6. int min(int a,int b){if(a<b)return a;return b;}    
  7. int judge(int s)    
  8. {    
  9.     int num=0;    
  10.     while(s)    
  11.     {    
  12.         if(s&1)num++;    
  13.         s>>=1;    
  14.     }    
  15.     return num;    
  16. }    
  17. int dist[11][11];    
  18. void init()    
  19. {    
  20.     for(int i=0;i<n;i++)    
  21.     for(int j=0;j<n;j++)    
  22.     {    
  23.         dist[i][j]=num[i][j];    
  24.     }    
  25.     for(int i=0;i<n;i++)    
  26.     for(int j=0;j<n;j++)    
  27.     for(int k=0;k<n;k++)    
  28.     if(dist[j][i]+dist[i][k]<dist[j][k])    
  29.     dist[j][k]=dist[j][i]+dist[i][k];    
  30.     for(int i=0;i<n;i++)    
  31.     for(int j=0;j<n;j++);    
  32.   //  printf("i=%d,j=%d,dist=%d\n",i,j,dist[i][j]);    
  33. }    
  34. int main()    
  35. {    
  36.   //  freopen("cin.txt","r",stdin);    
  37.     while(~scanf("%d",&n)&&n)    
  38.     {    
  39.         for(int i=0;i<=n;i++)    
  40.             for(int j=0;j<=n;j++)    
  41.                 scanf("%d",&num[i][j]);    
  42.         memset(dp,0x3f3f3f3f,sizeof(dp));    
  43.         dp[0][0]=0;    
  44.         n++;//have n+1 points    
  45.         init();    
  46.         for(int i=0;i<n;i++)//n points    
  47.             dp[1<<i|1][i]=dist[0][i];    
  48.        // for(int i=0;i<(1<<n)-1;i++) if(dp[i]!=0x3f3f3f3f)printf("i=%d  dp=%d   ",i,dp[i]);    
  49.         int ans=0x3f3f3f3f;    
  50.         for(int i=1;i<(1<<n)-1;i++)//now    
  51.         {    
  52.             for(int j=0;j<n;j++)//not exist    
  53.             {    
  54.                 if(i&(1<<j)) continue;    
  55.                 for(int k=0;k<n;k++)//exist    
  56.                 {    
  57.                     if(j==k) continue;    
  58.                     if(i&(1<<k))    
  59.                     {    
  60.                         dp[1<<j|i][j]=min(dp[i][k]+dist[k][j],dp[1<<j|i][j]);    
  61.                         if(judge(1<<j|i)==n)    
  62.                             ans=min(ans,dp[1<<j|i][j]+dist[j][0]);    
  63.                     }    
  64.                 }    
  65.             }    
  66.         }    
  67.         printf("%d\n",ans);    
  68.     }    
  69.     return 0;    
  70. }    
    #include <iostream>  
    #include<cstdio>  
    #include<cstring>  
    using namespace std;  
    int dp[1<<11][20],n,num[11][11];  
    int min(int a,int b){if(a<b)return a;return b;}  
    int judge(int s)  
    {  
        int num=0;  
        while(s)  
        {  
            if(s&1)num++;  
            s>>=1;  
        }  
        return num;  
    }  
    int dist[11][11];  
    void init()  
    {  
        for(int i=0;i<n;i++)  
        for(int j=0;j<n;j++)  
        {  
            dist[i][j]=num[i][j];  
        }  
        for(int i=0;i<n;i++)  
        for(int j=0;j<n;j++)  
        for(int k=0;k<n;k++)  
        if(dist[j][i]+dist[i][k]<dist[j][k])  
        dist[j][k]=dist[j][i]+dist[i][k];  
        for(int i=0;i<n;i++)  
        for(int j=0;j<n;j++);  
      //  printf("i=%d,j=%d,dist=%d\n",i,j,dist[i][j]);  
    }  
    int main()  
    {  
      //  freopen("cin.txt","r",stdin);  
        while(~scanf("%d",&n)&&n)  
        {  
            for(int i=0;i<=n;i++)  
                for(int j=0;j<=n;j++)  
                    scanf("%d",&num[i][j]);  
            memset(dp,0x3f3f3f3f,sizeof(dp));  
            dp[0][0]=0;  
            n++;//have n+1 points  
            init();  
            for(int i=0;i<n;i++)//n points  
                dp[1<<i|1][i]=dist[0][i];  
           // for(int i=0;i<(1<<n)-1;i++) if(dp[i]!=0x3f3f3f3f)printf("i=%d  dp=%d   ",i,dp[i]);  
            int ans=0x3f3f3f3f;  
            for(int i=1;i<(1<<n)-1;i++)//now  
            {  
                for(int j=0;j<n;j++)//not exist  
                {  
                    if(i&(1<<j)) continue;  
                    for(int k=0;k<n;k++)//exist  
                    {  
                        if(j==k) continue;  
                        if(i&(1<<k))  
                        {  
                            dp[1<<j|i][j]=min(dp[i][k]+dist[k][j],dp[1<<j|i][j]);  
                            if(judge(1<<j|i)==n)  
                                ans=min(ans,dp[1<<j|i][j]+dist[j][0]);  
                        }  
                    }  
                }  
            }  
            printf("%d\n",ans);  
        }  
        return 0;  
    }  

18、 建全国的路的一部分,依旧要求联通,但是首都到各个城市的最短距离不变的前提下求最小花费

Aizu 2249Road Construction 单源最短路变形 spfa模板改写

既然是首都到各地的距离最短前提下求最小花费,那么松弛操作当距离相等的时候压入花费小的就可以啦

  1. #include <stdio.h>    
  2. #include <string.h>    
  3. #include <queue>    
  4. #include <iostream>    
  5. #include <algorithm>    
  6. using namespace std;    
  7. const int maxn=10050;    
  8. const int maxe=2005000;    
  9. const int INF=1e9;    
  10. struct note    
  11. {    
  12.     int to;    
  13.     int w;    
  14.     int c;    
  15.     int next;    
  16. };    
  17. note edge[maxe];    
  18. int head[maxn];    
  19. int ip;    
  20. void init()    
  21. {    
  22.     memset(head,-1,sizeof(head));    
  23.     ip=0;    
  24. }    
  25. void addedge(int u,int v,int w,int c)    
  26. {    
  27.     edge[ip].to=v;    
  28.     edge[ip].c=c;    
  29.     edge[ip].w=w;    
  30.     edge[ip].next=head[u];    
  31.     head[u]=ip++;    
  32. }    
  33. int cost[maxn];    
  34. int dis[maxn];    
  35. bool vis[maxn];    
  36. queue<int>q;    
  37. void spfa(int s,int n)    
  38. {    
  39.     while(!q.empty())q.pop();    
  40.     for(int i=1;i<=n;i++)    
  41.         cost[i]=dis[i]=INF;    
  42.     memset(vis,false,sizeof(vis));    
  43.     dis[s]=0;    
  44.     cost[s]=0;    
  45.     vis[s]=true;    
  46.     q.push(s);    
  47.     while(!q.empty())    
  48.     {    
  49.         int u=q.front();    
  50.         q.pop();    
  51.         vis[u]=false;    
  52.         for(int i=head[u];i!=-1;i=edge[i].next)    
  53.         {    
  54.             int to=edge[i].to;    
  55.             int val=edge[i].w;    
  56.             if(dis[to]>dis[u]+val||(dis[to]==dis[u]+val&&cost[to]>edge[i].c))//有多条最短路时,取花费最小的    
  57.             {    
  58.                 dis[to]=dis[u]+val;    
  59.                 cost[to]=edge[i].c;    
  60.                 if(!vis[to])    
  61.                 {    
  62.                     q.push(to);    
  63.                     vis[to]=true;    
  64.                 }    
  65.             }    
  66.         }    
  67.     }    
  68. }    
  69. int main()    
  70. {    
  71.    // freopen("cin.txt","r",stdin);    
  72.     int n,m;    
  73.     int u,v,w,c;    
  74.     while(~scanf("%d%d",&n,&m))    
  75.     {    
  76.         if(n==0&&m==0) break;    
  77.         init();    
  78.         for(int i=0;i<m;i++)    
  79.         {    
  80.             scanf("%d%d%d%d",&u,&v,&c,&w);    
  81.             addedge(u,v,c,w);    
  82.             addedge(v,u,c,w);    
  83.         }    
  84.         spfa(1,n);    
  85.         int ans=0;    
  86.         for(int i=1;i<=n;i++)    
  87.             ans+=cost[i];    
  88.         printf("%d\n",ans);    
  89.     }    
  90.     return 0;    
  91. }    
    #include <stdio.h>  
    #include <string.h>  
    #include <queue>  
    #include <iostream>  
    #include <algorithm>  
    using namespace std;  
    const int maxn=10050;  
    const int maxe=2005000;  
    const int INF=1e9;  
    struct note  
    {  
        int to;  
        int w;  
        int c;  
        int next;  
    };  
    note edge[maxe];  
    int head[maxn];  
    int ip;  
    void init()  
    {  
        memset(head,-1,sizeof(head));  
        ip=0;  
    }  
    void addedge(int u,int v,int w,int c)  
    {  
        edge[ip].to=v;  
        edge[ip].c=c;  
        edge[ip].w=w;  
        edge[ip].next=head[u];  
        head[u]=ip++;  
    }  
    int cost[maxn];  
    int dis[maxn];  
    bool vis[maxn];  
    queue<int>q;  
    void spfa(int s,int n)  
    {  
        while(!q.empty())q.pop();  
        for(int i=1;i<=n;i++)  
            cost[i]=dis[i]=INF;  
        memset(vis,false,sizeof(vis));  
        dis[s]=0;  
        cost[s]=0;  
        vis[s]=true;  
        q.push(s);  
        while(!q.empty())  
        {  
            int u=q.front();  
            q.pop();  
            vis[u]=false;  
            for(int i=head[u];i!=-1;i=edge[i].next)  
            {  
                int to=edge[i].to;  
                int val=edge[i].w;  
                if(dis[to]>dis[u]+val||(dis[to]==dis[u]+val&&cost[to]>edge[i].c))//有多条最短路时,取花费最小的  
                {  
                    dis[to]=dis[u]+val;  
                    cost[to]=edge[i].c;  
                    if(!vis[to])  
                    {  
                        q.push(to);  
                        vis[to]=true;  
                    }  
                }  
            }  
        }  
    }  
    int main()  
    {  
       // freopen("cin.txt","r",stdin);  
        int n,m;  
        int u,v,w,c;  
        while(~scanf("%d%d",&n,&m))  
        {  
            if(n==0&&m==0) break;  
            init();  
            for(int i=0;i<m;i++)  
            {  
                scanf("%d%d%d%d",&u,&v,&c,&w);  
                addedge(u,v,c,w);  
                addedge(v,u,c,w);  
            }  
            spfa(1,n);  
            int ans=0;  
            for(int i=1;i<=n;i++)  
                ans+=cost[i];  
            printf("%d\n",ans);  
        }  
        return 0;  
    }  

19、 差分约束系统

uva11478 Halum【二分+差分约束】

题意:对于给定有向图,定义一种操作:对于选定的某一点,进入这个点的所有边权都减去d,从这个点出去的所有边权都加上d。经过一系列的操作,使得所有边权的最小值达到最大,需保证这个最值是正数

把点当做最短路的点假设每个点都有一个点权sum(a),而w(a,b)+sum(a)-sum(b)>=x,x是所有边权的最小值,把边权sum放到等号右边,就构成了差分约束的不等式组,,保证不出现负环的spfa就是最大的x求得的。

by the way Spfa要是最开始不加超级源点,就要把所有的点都压入队列

这么看来就和上面的题一样啦

  1. #include <iostream>    
  2. #include<cstdio>    
  3. #include<cstring>    
  4. #include<vector>    
  5. #include<queue>    
  6. using namespace std;    
  7. const int inf=0x3f3f;    
  8. const int maxn=505;    
  9. int n,m;    
  10. struct Edge    
  11. {    
  12.     int v,cost;    
  13.     Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}    
  14. };    
  15. vector<Edge>E[maxn];    
  16. void addedge(int u,int v,int w)    
  17. {    
  18.     E[u].push_back(Edge(v,w));    
  19. }    
  20. bool vis[maxn];    
  21. int cnt[maxn];    
  22. int dist[maxn];    
  23. bool spfa(int start,int n)    
  24. {    
  25.     memset(vis,false,sizeof(vis));    
  26.     memset(dist,inf,sizeof(dist));    
  27.     vis[start]=true;    
  28.     dist[start]=0;    
  29.     queue<int>que;    
  30.     while(!que.empty()) que.pop();    
  31.     que.push(start);    
  32.     memset(cnt,0,sizeof(cnt));    
  33.     cnt[start]=1;    
  34.     while(!que.empty())    
  35.     {    
  36.         int u=que.front();    
  37.         que.pop();    
  38.         vis[u]=false;    
  39.         for(int i=0;i<E[u].size();i++)    
  40.         {    
  41.             int v=E[u][i].v;    
  42.             if(dist[v]>dist[u]+E[u][i].cost)    
  43.             {    
  44.                 dist[v]=dist[u]+E[u][i].cost;    
  45.                 if(!vis[v])    
  46.                 {    
  47.                     vis[v]=true;    
  48.                     que.push(v);    
  49.                     if(++cnt[v]>n) return false;    
  50.                 }    
  51.             }    
  52.         }    
  53.     }    
  54.     return true;    
  55. }    
  56. bool judge(int x)    
  57. {    
  58.    // cout<<"rrr"<<endl;    
  59.     for(int i=1;i<=n;i++)    
  60.     {    
  61.         for(int j=0;j<E[i].size();j++)    
  62.             E[i][j].cost-=x;    
  63.     }    
  64.     bool flag=spfa(0,n);    
  65.     for(int i=1;i<=n;i++)    
  66.     {    
  67.         for(int j=0;j<E[i].size();j++)    
  68.             E[i][j].cost+=x;    
  69.     }    
  70.     return flag;    
  71. }    
  72.     int main()    
  73.     {    
  74.         //freopen("cin.txt","r",stdin);    
  75.        // int cas=1;    
  76.        // scanf("%d",&t);    
  77.         while(~scanf("%d%d",&n,&m))    
  78.         {    
  79.            // printf("Case #%d: ",cas++);    
  80.             for(int i=0;i<=n;i++) E[i].clear();    
  81.         //    memset(head,-1,sizeof(head));    
  82.             int l=1,mid,r=-inf;    
  83.             while(m--)    
  84.             {    
  85.                 int a,b;    
  86.                 int c;    
  87.                 scanf("%d%d%d",&a,&b,&c);    
  88.                 addedge(a,b,c);    
  89.                 if(c>r)r=c;    
  90.             }    
  91.             for(int i=1;i<=n;i++)addedge(0,i,0);    
  92.           //  cout<<"rrr"<<endl;    
  93.            // printf("r=%d\n",r);    
  94.             if(judge(r))    
  95.             {    
  96.                 printf("Infinite\n");    
  97.                 continue;    
  98.             }    
  99.             else if(!judge(1))    
  100.             {    
  101.                 puts("No Solution");    
  102.                 continue;    
  103.             }    
  104.             int ans;    
  105.             while(l<=r)    
  106.             {    
  107.                 mid=(l+r)/2;    
  108.                // cout<<mid<<endl;    
  109.                // printf("l=%d,mid=%d,r=%d    ",l,mid,r);    
  110.                 if(judge(mid)) ans=mid,l=mid+1;    
  111.                 else {r=mid-1;}    
  112.                // printf("l=%d,mid=%d,r=%d,ans=%d\n",l,mid,r,ans);    
  113.             }    
  114.             printf("%d\n",ans);    
  115.         }    
  116.         return 0;    
  117.     }    
    #include <iostream>  
    #include<cstdio>  
    #include<cstring>  
    #include<vector>  
    #include<queue>  
    using namespace std;  
    const int inf=0x3f3f;  
    const int maxn=505;  
    int n,m;  
    struct Edge  
    {  
        int v,cost;  
        Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}  
    };  
    vector<Edge>E[maxn];  
    void addedge(int u,int v,int w)  
    {  
        E[u].push_back(Edge(v,w));  
    }  
    bool vis[maxn];  
    int cnt[maxn];  
    int dist[maxn];  
    bool spfa(int start,int n)  
    {  
        memset(vis,false,sizeof(vis));  
        memset(dist,inf,sizeof(dist));  
        vis[start]=true;  
        dist[start]=0;  
        queue<int>que;  
        while(!que.empty()) que.pop();  
        que.push(start);  
        memset(cnt,0,sizeof(cnt));  
        cnt[start]=1;  
        while(!que.empty())  
        {  
            int u=que.front();  
            que.pop();  
            vis[u]=false;  
            for(int i=0;i<E[u].size();i++)  
            {  
                int v=E[u][i].v;  
                if(dist[v]>dist[u]+E[u][i].cost)  
                {  
                    dist[v]=dist[u]+E[u][i].cost;  
                    if(!vis[v])  
                    {  
                        vis[v]=true;  
                        que.push(v);  
                        if(++cnt[v]>n) return false;  
                    }  
                }  
            }  
        }  
        return true;  
    }  
    bool judge(int x)  
    {  
       // cout<<"rrr"<<endl;  
        for(int i=1;i<=n;i++)  
        {  
            for(int j=0;j<E[i].size();j++)  
                E[i][j].cost-=x;  
        }  
        bool flag=spfa(0,n);  
        for(int i=1;i<=n;i++)  
        {  
            for(int j=0;j<E[i].size();j++)  
                E[i][j].cost+=x;  
        }  
        return flag;  
    }  
        int main()  
        {  
            //freopen("cin.txt","r",stdin);  
           // int cas=1;  
           // scanf("%d",&t);  
            while(~scanf("%d%d",&n,&m))  
            {  
               // printf("Case #%d: ",cas++);  
                for(int i=0;i<=n;i++) E[i].clear();  
            //    memset(head,-1,sizeof(head));  
                int l=1,mid,r=-inf;  
                while(m--)  
                {  
                    int a,b;  
                    int c;  
                    scanf("%d%d%d",&a,&b,&c);  
                    addedge(a,b,c);  
                    if(c>r)r=c;  
                }  
                for(int i=1;i<=n;i++)addedge(0,i,0);  
              //  cout<<"rrr"<<endl;  
               // printf("r=%d\n",r);  
                if(judge(r))  
                {  
                    printf("Infinite\n");  
                    continue;  
                }  
                else if(!judge(1))  
                {  
                    puts("No Solution");  
                    continue;  
                }  
                int ans;  
                while(l<=r)  
                {  
                    mid=(l+r)/2;  
                   // cout<<mid<<endl;  
                   // printf("l=%d,mid=%d,r=%d    ",l,mid,r);  
                    if(judge(mid)) ans=mid,l=mid+1;  
                    else {r=mid-1;}  
                   // printf("l=%d,mid=%d,r=%d,ans=%d\n",l,mid,r,ans);  
                }  
                printf("%d\n",ans);  
            }  
            return 0;  
        }  




20、二分找负环

UVA - 11090 Going in Cycle!! 【Bellman-Ford算法判负环 二分】

一样的题:给定有向带权图,求最小环的值。二分找最小值,边权都减去这个数

  1. #include <iostream>    
  2. #include<cstdio>    
  3. #include<cstring>    
  4. #include<vector>    
  5. using namespace std;    
  6. const double inf=0x3f3f3f3f;    
  7. const int maxn=100;    
  8. int n,m,t;    
  9. double dist[maxn];    
  10. struct Edge    
  11. {    
  12.     int u,v;    
  13.     double cost;    
  14.     Edge(int _u=0,int _v=0,double _cost=0):u(_u),v(_v),cost(_cost){}    
  15. };    
  16. vector<Edge>E;    
  17. bool bellman(int start,int n)    
  18. {    
  19.     for(int i=1;i<=n;i++)dist[i]=inf;    
  20.     dist[start]=0;    
  21.     for(int i=1;i<n;i++)    
  22.     {    
  23.         bool flag=false;    
  24.         for(int j=0;j<E.size();j++)    
  25.         {    
  26.             int u=E[j].u;    
  27.             int v=E[j].v;    
  28.             double cost=E[j].cost;    
  29.             if(dist[v]>dist[u]+cost)    
  30.             {    
  31.                 dist[v]=dist[u]+cost;    
  32.                 flag=true;    
  33.             }    
  34.         }    
  35.         if(!flag)return true;    
  36.     }    
  37.     for(int j=0;j<E.size();j++)    
  38.         if(dist[E[j].v]>dist[E[j].u]+E[j].cost)    
  39.             return false;    
  40.     return true;    
  41. }    
  42. bool judge(double x)    
  43. {    
  44.     for(int i=0;i<E.size();i++) E[i].cost-=x;    
  45.     bool flag=bellman(1,n);    
  46.     for(int i=0;i<E.size();i++) E[i].cost+=x;    
  47.     return flag;    
  48. }    
  49. int main()    
  50. {    
  51.     //freopen("cin.txt","r",stdin);    
  52.     int cas=1;    
  53.     scanf("%d",&t);    
  54.     while(t--)    
  55.     {    
  56.         scanf("%d%d",&n,&m);    
  57.         printf("Case #%d: ",cas++);    
  58.         E.clear();    
  59.         double r=0.0;    
  60.         while(m--)    
  61.         {    
  62.             int a,b;    
  63.             double c;    
  64.             scanf("%d%d%lf",&a,&b,&c);    
  65.             E.push_back(Edge(a,b,c));    
  66.             if(c>r)r=c;    
  67.         }    
  68.       //  printf("r=%lf\n",r);    
  69.         if(judge(r+1))    
  70.         {    
  71.             printf("No cycle found.\n");    
  72.             continue;    
  73.         }    
  74.         double l=0.0,mid;    
  75.         while(r-l>=0.0001)    
  76.         {    
  77.             mid=(l+r)/2;    
  78.             for(int i=0;i<E.size();i++) E[i].cost-=mid;    
  79.             if(bellman(1,n)) l=mid;    
  80.             else r=mid;    
  81.             for(int i=0;i<E.size();i++) E[i].cost+=mid;    
  82.         }    
  83.         printf("%.2lf\n",r);    
  84.     }    
  85.     return 0;    
  86. }    
    #include <iostream>  
    #include<cstdio>  
    #include<cstring>  
    #include<vector>  
    using namespace std;  
    const double inf=0x3f3f3f3f;  
    const int maxn=100;  
    int n,m,t;  
    double dist[maxn];  
    struct Edge  
    {  
        int u,v;  
        double cost;  
        Edge(int _u=0,int _v=0,double _cost=0):u(_u),v(_v),cost(_cost){}  
    };  
    vector<Edge>E;  
    bool bellman(int start,int n)  
    {  
        for(int i=1;i<=n;i++)dist[i]=inf;  
        dist[start]=0;  
        for(int i=1;i<n;i++)  
        {  
            bool flag=false;  
            for(int j=0;j<E.size();j++)  
            {  
                int u=E[j].u;  
                int v=E[j].v;  
                double cost=E[j].cost;  
                if(dist[v]>dist[u]+cost)  
                {  
                    dist[v]=dist[u]+cost;  
                    flag=true;  
                }  
            }  
            if(!flag)return true;  
        }  
        for(int j=0;j<E.size();j++)  
            if(dist[E[j].v]>dist[E[j].u]+E[j].cost)  
                return false;  
        return true;  
    }  
    bool judge(double x)  
    {  
        for(int i=0;i<E.size();i++) E[i].cost-=x;  
        bool flag=bellman(1,n);  
        for(int i=0;i<E.size();i++) E[i].cost+=x;  
        return flag;  
    }  
    int main()  
    {  
        //freopen("cin.txt","r",stdin);  
        int cas=1;  
        scanf("%d",&t);  
        while(t--)  
        {  
            scanf("%d%d",&n,&m);  
            printf("Case #%d: ",cas++);  
            E.clear();  
            double r=0.0;  
            while(m--)  
            {  
                int a,b;  
                double c;  
                scanf("%d%d%lf",&a,&b,&c);  
                E.push_back(Edge(a,b,c));  
                if(c>r)r=c;  
            }  
          //  printf("r=%lf\n",r);  
            if(judge(r+1))  
            {  
                printf("No cycle found.\n");  
                continue;  
            }  
            double l=0.0,mid;  
            while(r-l>=0.0001)  
            {  
                mid=(l+r)/2;  
                for(int i=0;i<E.size();i++) E[i].cost-=mid;  
                if(bellman(1,n)) l=mid;  
                else r=mid;  
                for(int i=0;i<E.size();i++) E[i].cost+=mid;  
            }  
            printf("%.2lf\n",r);  
        }  
        return 0;  
    }  



21、

hdu4786Fibonacci Tree【kruskal最小生成树】

给定无向图每个边要么是白色,要么是黑色。求生成树的白边个数能否是斐波那契数。其实应该能想到的,让白边是1,黑边是0,求最大生成树和最小生成树。看中间范围是否有斐波那契数。

  1. #include <iostream>    
  2. #include<cstdio>    
  3. #include<cstring>    
  4. #include<algorithm>    
  5. using namespace std;    
  6. const int maxn=200005;    
  7. const int maxm=200005;    
  8. int F[maxn];    
  9. struct Edge    
  10. {    
  11.     int u,v,w;    
  12. }edge[maxm];    
  13. int tol;    
  14. void addedge(int u,int v,int w)    
  15. {    
  16.     edge[tol].v=v;    
  17.     edge[tol].u=u;    
  18.     edge[tol++].w=w;    
  19. }    
  20. bool cmp(Edge a,Edge b)    
  21. {    
  22.     return a.w<b.w;    
  23. }    
  24. bool cmp2(Edge a,Edge b)    
  25. {    
  26.     return a.w>b.w;    
  27. }    
  28. int fnd(int x)    
  29. {    
  30.     return x==F[x]?x:F[x]=fnd(F[x]);    
  31. }    
  32. int kruskal(int n)    
  33. {    
  34.     for(int i=1;i<=n;i++) F[i]=i;    
  35.    // sort(edge,edge+tol,cmp);    
  36.     int cnt=0;    
  37.     int ans=0;    
  38.     for(int i=0;i<tol;i++)    
  39.     {    
  40.         int u=edge[i].u;    
  41.         int v=edge[i].v;    
  42.         int w=edge[i].w;    
  43.         int a=fnd(u);    
  44.         int b=fnd(v);    
  45.         if(a!=b)    
  46.         {    
  47.             ans+=w;    
  48.             F[b]=a;    
  49.             cnt++;    
  50.         }    
  51.         if(cnt==n-1)break;    
  52.     }    
  53.     if(cnt<n-1)return -1;    
  54.     return ans;    
  55. }    
  56. int num[100],cnt;    
  57. void init()    
  58. {    
  59.     num[0]=0;num[1]=1;num[2]=2;num[3]=3;    
  60.     cnt=4;    
  61.     while(num[cnt-1]<=100005)    
  62.     {    
  63.         num[cnt]=num[cnt-1]+num[cnt-2];    
  64.         cnt++;    
  65.        // cout<<num[cnt-1]<<endl;    
  66.     }    
  67. }    
  68. int main()    
  69. {    
  70.     //freopen("cin.txt","r",stdin);    
  71.     int t,n,m,cas=1;    
  72.     scanf("%d",&t);    
  73.     init();    
  74.     while(t--)    
  75.     {    
  76.         scanf("%d%d",&n,&m);    
  77.         tol=0;    
  78.         while(m--)    
  79.         {    
  80.             int u,v,w;    
  81.             scanf("%d%d%d",&u,&v,&w);    
  82.             addedge(u,v,w);    
  83.             addedge(v,u,w);///!!!    
  84.         }    
  85.         printf("Case #%d: ",cas++);    
  86.         sort(edge,edge+tol,cmp);    
  87.         int small=kruskal(n);    
  88.         bool ff=true;    
  89.         sort(edge,edge+tol,cmp2);    
  90.         int big=kruskal(n);    
  91.        // printf("s=%d,b=%d\n",small,big);    
  92.         if(small==-1||big==-1)    
  93.         {    
  94.             puts("No");    
  95.             continue;    
  96.         }    
  97.         bool flag=false;    
  98.         for(int i=1;i<=23;i++)    
  99.         {    
  100.             if(num[i]>=small&&num[i]<=big)    
  101.             {    
  102.                 flag=true;    
  103.                 break;    
  104.             }    
  105.         }    
  106.         if(flag) printf("Yes\n");    
  107.         else printf("No\n");    
  108.     }    
  109.     return 0;    
  110. }    
    #include <iostream>  
    #include<cstdio>  
    #include<cstring>  
    #include<algorithm>  
    using namespace std;  
    const int maxn=200005;  
    const int maxm=200005;  
    int F[maxn];  
    struct Edge  
    {  
        int u,v,w;  
    }edge[maxm];  
    int tol;  
    void addedge(int u,int v,int w)  
    {  
        edge[tol].v=v;  
        edge[tol].u=u;  
        edge[tol++].w=w;  
    }  
    bool cmp(Edge a,Edge b)  
    {  
        return a.w<b.w;  
    }  
    bool cmp2(Edge a,Edge b)  
    {  
        return a.w>b.w;  
    }  
    int fnd(int x)  
    {  
        return x==F[x]?x:F[x]=fnd(F[x]);  
    }  
    int kruskal(int n)  
    {  
        for(int i=1;i<=n;i++) F[i]=i;  
       // sort(edge,edge+tol,cmp);  
        int cnt=0;  
        int ans=0;  
        for(int i=0;i<tol;i++)  
        {  
            int u=edge[i].u;  
            int v=edge[i].v;  
            int w=edge[i].w;  
            int a=fnd(u);  
            int b=fnd(v);  
            if(a!=b)  
            {  
                ans+=w;  
                F[b]=a;  
                cnt++;  
            }  
            if(cnt==n-1)break;  
        }  
        if(cnt<n-1)return -1;  
        return ans;  
    }  
    int num[100],cnt;  
    void init()  
    {  
        num[0]=0;num[1]=1;num[2]=2;num[3]=3;  
        cnt=4;  
        while(num[cnt-1]<=100005)  
        {  
            num[cnt]=num[cnt-1]+num[cnt-2];  
            cnt++;  
           // cout<<num[cnt-1]<<endl;  
        }  
    }  
    int main()  
    {  
        //freopen("cin.txt","r",stdin);  
        int t,n,m,cas=1;  
        scanf("%d",&t);  
        init();  
        while(t--)  
        {  
            scanf("%d%d",&n,&m);  
            tol=0;  
            while(m--)  
            {  
                int u,v,w;  
                scanf("%d%d%d",&u,&v,&w);  
                addedge(u,v,w);  
                addedge(v,u,w);///!!!  
            }  
            printf("Case #%d: ",cas++);  
            sort(edge,edge+tol,cmp);  
            int small=kruskal(n);  
            bool ff=true;  
            sort(edge,edge+tol,cmp2);  
            int big=kruskal(n);  
           // printf("s=%d,b=%d\n",small,big);  
            if(small==-1||big==-1)  
            {  
                puts("No");  
                continue;  
            }  
            bool flag=false;  
            for(int i=1;i<=23;i++)  
            {  
                if(num[i]>=small&&num[i]<=big)  
                {  
                    flag=true;  
                    break;  
                }  
            }  
            if(flag) printf("Yes\n");  
            else printf("No\n");  
        }  
        return 0;  
    }  

22、2015多校第一场(盗墓笔记)

hdu5294Tricks Device【最短路+网络流】

从1开始到n结束,给出双向道路,问至少去掉多少边最短路不是原始最短路长度,至多去掉多少条边最短路长度不变

分别利用1与n作为源点 ,分别跑一遍最短路,这个时候两个dist数组记录的就是以1、n为源点的单源最短路长度,理论上他俩无缝接起来都是最短路的方案(理论上是,实际上也是:P  )那么我就依次验证给定的边长是否在最短路上,在的话,给这对点建网络流的边(这个题最最讨厌的地方在于函数名,数组名都差不多,特别容易写错)流量是题中给定的第三个数组,求完最短路还要给这对点再建一遍最短路的边,边长为一,这样跑下来dist[n]就是最短路的最短长度了

  1. #include <iostream>    
  2. #include<cstdio>    
  3. #include<cstring>    
  4. #include<vector>    
  5. #include<queue>    
  6. using namespace std;    
  7. const int inf=0x3f3f;    
  8. const int maxn=2111;    
  9. int n,m;    
  10. struct Edge    
  11. {    
  12.     int v,cost;    
  13.     Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}    
  14. };    
  15. vector<Edge>E[maxn];    
  16. void addedge(int u,int v,int w)    
  17. {    
  18.     E[u].push_back(Edge(v,w));    
  19. }    
  20. bool vis[maxn];    
  21. int cnt[maxn];    
  22. int dist[maxn],dist1[maxn];    
  23. bool spfa(int start,int n)    
  24. {    
  25.     memset(vis,false,sizeof(vis));    
  26.     memset(dist,inf,sizeof(dist));    
  27.     vis[start]=true;    
  28.     dist[start]=0;    
  29.     queue<int>que;    
  30.     while(!que.empty()) que.pop();    
  31.     que.push(start);    
  32.     memset(cnt,0,sizeof(cnt));    
  33.     cnt[start]=1;    
  34.     while(!que.empty())    
  35.     {    
  36.         int u=que.front();    
  37.         que.pop();    
  38.         vis[u]=false;    
  39.         for(int i=0;i<E[u].size();i++)    
  40.         {    
  41.             int v=E[u][i].v;    
  42.             if(dist[v]>dist[u]+E[u][i].cost)    
  43.             {    
  44.                 dist[v]=dist[u]+E[u][i].cost;    
  45.                 if(!vis[v])    
  46.                 {    
  47.                     vis[v]=true;    
  48.                     que.push(v);    
  49.                     if(++cnt[v]>n) return false;    
  50.                 }    
  51.             }    
  52.         }    
  53.     }    
  54.     return true;    
  55. }    
  56. int w[60009],u[60009],v[60009];    
  57.     
  58. const int mm=161111;    
  59. const int mn=600009;    
  60. const int oo=1000000000;    
  61. int node,src,dest,edge;    
  62. int reach[mm],flow[mm],nxt[mm];    
  63. int head[mn],work[mn],dis[mn],q[mn];    
  64. inline int min(int a,int b)    
  65. {    
  66.     return a<b?a:b;    
  67. }    
  68. inline void prepare(int _node,int _src,int _dest)    
  69. {    
  70.     node=_node,src=_src,dest=_dest;    
  71.     for(int i=0;i<node;++i)head[i]=-1;    
  72.     edge=0;    
  73. }    
  74. inline void addedge(int u,int v,int c1,int c2)    
  75. {    
  76.     reach[edge]=v,flow[edge]=c1,nxt[edge]=head[u],head[u]=edge++;    
  77.     reach[edge]=u,flow[edge]=c2,nxt[edge]=head[v],head[v]=edge++;    
  78. }    
  79. bool Dinic_bfs()    
  80. {    
  81.     int i,u,v,l,r=0;    
  82.     for(i=0;i<node;++i)dis[i]=-1;    
  83.     dis[q[r++]=src]=0;    
  84.     for(l=0;l<r;++l)    
  85.         for(i=head[u=q[l]];i>=0;i=nxt[i])    
  86.             if(flow[i]&&dis[v=reach[i]]<0)    
  87.             {    
  88.                 dis[q[r++]=v]=dis[u]+1;    
  89.                 if(v==dest)return 1;    
  90.             }    
  91.     return 0;    
  92. }    
  93. int Dinic_dfs(int u,int exp)    
  94. {    
  95.     if(u==dest)return exp;    
  96.     for(int &i=work[u],v,tmp;i>=0;i=nxt[i])    
  97.         if(flow[i]&&dis[v=reach[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>0)    
  98.         {    
  99.             flow[i]-=tmp;    
  100.             flow[i^1]+=tmp;    
  101.             return tmp;    
  102.         }dis[u]--;    
  103.     return 0;    
  104. }    
  105. int Dinic_flow()    
  106. {    
  107.     int i,ret=0,delta;    
  108.     while(Dinic_bfs())    
  109.     {    
  110.         for(i=0;i<node;++i)work[i]=head[i];    
  111.         while(delta=Dinic_dfs(src,oo))ret+=delta;    
  112.     }    
  113.     return ret;    
  114. }    
  115. int bb[mn][2],dist2[mn];    
  116. int main()    
  117. {    
  118.    // freopen("cin.txt","r",stdin);    
  119.     while(~scanf("%d%d",&n,&m))    
  120.     {    
  121.         for(int i=0;i<=n;i++) E[i].clear();    
  122.         for(int i=0;i<m;i++)    
  123.         {    
  124.             scanf("%d%d%d",&u[i],&v[i],&w[i]);    
  125.             addedge(u[i],v[i],w[i]);    
  126.             addedge(v[i],u[i],w[i]);    
  127.         }    
  128.         spfa(1,n);    
  129.         memcpy(dist2,dist,sizeof(dist));    
  130.         spfa(n,n);    
  131.         int k=0;    
  132.         for(int i=0;i<m;i++)    
  133.         {    
  134.             if(dist2[u[i]]>dist2[v[i]])swap(u[i],v[i]);    
  135.             if(dist[v[i]]+w[i]+dist2[u[i]]==dist2[n])    
  136.             {    
  137.                 bb[k][0]=u[i];    
  138.                 bb[k++][1]=v[i];    
  139.             }    
  140.         }    
  141.         prepare(n+1,1,n);    
  142.         for(int i=0;i<k;i++)    
  143.         {    
  144.             addedge(bb[i][0],bb[i][1],1,0);    
  145.            // addedge(bb[i][1],bb[i][0],1);    
  146.         }    
  147.         int x=Dinic_flow();    
  148.         for(int i=0;i<=n;i++) E[i].clear();    
  149.         for(int i=0;i<k;i++)    
  150.         {    
  151.             addedge(bb[i][0],bb[i][1],1);    
  152.             addedge(bb[i][1],bb[i][0],1);    
  153.         }    
  154.         spfa(1,n);    
  155.         printf("%d %d\n",x,m-dist[n]);    
  156.     }    
  157.     return 0;    
  158. }    
    #include <iostream>  
    #include<cstdio>  
    #include<cstring>  
    #include<vector>  
    #include<queue>  
    using namespace std;  
    const int inf=0x3f3f;  
    const int maxn=2111;  
    int n,m;  
    struct Edge  
    {  
        int v,cost;  
        Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}  
    };  
    vector<Edge>E[maxn];  
    void addedge(int u,int v,int w)  
    {  
        E[u].push_back(Edge(v,w));  
    }  
    bool vis[maxn];  
    int cnt[maxn];  
    int dist[maxn],dist1[maxn];  
    bool spfa(int start,int n)  
    {  
        memset(vis,false,sizeof(vis));  
        memset(dist,inf,sizeof(dist));  
        vis[start]=true;  
        dist[start]=0;  
        queue<int>que;  
        while(!que.empty()) que.pop();  
        que.push(start);  
        memset(cnt,0,sizeof(cnt));  
        cnt[start]=1;  
        while(!que.empty())  
        {  
            int u=que.front();  
            que.pop();  
            vis[u]=false;  
            for(int i=0;i<E[u].size();i++)  
            {  
                int v=E[u][i].v;  
                if(dist[v]>dist[u]+E[u][i].cost)  
                {  
                    dist[v]=dist[u]+E[u][i].cost;  
                    if(!vis[v])  
                    {  
                        vis[v]=true;  
                        que.push(v);  
                        if(++cnt[v]>n) return false;  
                    }  
                }  
            }  
        }  
        return true;  
    }  
    int w[60009],u[60009],v[60009];  
      
    const int mm=161111;  
    const int mn=600009;  
    const int oo=1000000000;  
    int node,src,dest,edge;  
    int reach[mm],flow[mm],nxt[mm];  
    int head[mn],work[mn],dis[mn],q[mn];  
    inline int min(int a,int b)  
    {  
        return a<b?a:b;  
    }  
    inline void prepare(int _node,int _src,int _dest)  
    {  
        node=_node,src=_src,dest=_dest;  
        for(int i=0;i<node;++i)head[i]=-1;  
        edge=0;  
    }  
    inline void addedge(int u,int v,int c1,int c2)  
    {  
        reach[edge]=v,flow[edge]=c1,nxt[edge]=head[u],head[u]=edge++;  
        reach[edge]=u,flow[edge]=c2,nxt[edge]=head[v],head[v]=edge++;  
    }  
    bool Dinic_bfs()  
    {  
        int i,u,v,l,r=0;  
        for(i=0;i<node;++i)dis[i]=-1;  
        dis[q[r++]=src]=0;  
        for(l=0;l<r;++l)  
            for(i=head[u=q[l]];i>=0;i=nxt[i])  
                if(flow[i]&&dis[v=reach[i]]<0)  
                {  
                    dis[q[r++]=v]=dis[u]+1;  
                    if(v==dest)return 1;  
                }  
        return 0;  
    }  
    int Dinic_dfs(int u,int exp)  
    {  
        if(u==dest)return exp;  
        for(int &i=work[u],v,tmp;i>=0;i=nxt[i])  
            if(flow[i]&&dis[v=reach[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>0)  
            {  
                flow[i]-=tmp;  
                flow[i^1]+=tmp;  
                return tmp;  
            }dis[u]--;  
        return 0;  
    }  
    int Dinic_flow()  
    {  
        int i,ret=0,delta;  
        while(Dinic_bfs())  
        {  
            for(i=0;i<node;++i)work[i]=head[i];  
            while(delta=Dinic_dfs(src,oo))ret+=delta;  
        }  
        return ret;  
    }  
    int bb[mn][2],dist2[mn];  
    int main()  
    {  
       // freopen("cin.txt","r",stdin);  
        while(~scanf("%d%d",&n,&m))  
        {  
            for(int i=0;i<=n;i++) E[i].clear();  
            for(int i=0;i<m;i++)  
            {  
                scanf("%d%d%d",&u[i],&v[i],&w[i]);  
                addedge(u[i],v[i],w[i]);  
                addedge(v[i],u[i],w[i]);  
            }  
            spfa(1,n);  
            memcpy(dist2,dist,sizeof(dist));  
            spfa(n,n);  
            int k=0;  
            for(int i=0;i<m;i++)  
            {  
                if(dist2[u[i]]>dist2[v[i]])swap(u[i],v[i]);  
                if(dist[v[i]]+w[i]+dist2[u[i]]==dist2[n])  
                {  
                    bb[k][0]=u[i];  
                    bb[k++][1]=v[i];  
                }  
            }  
            prepare(n+1,1,n);  
            for(int i=0;i<k;i++)  
            {  
                addedge(bb[i][0],bb[i][1],1,0);  
               // addedge(bb[i][1],bb[i][0],1);  
            }  
            int x=Dinic_flow();  
            for(int i=0;i<=n;i++) E[i].clear();  
            for(int i=0;i<k;i++)  
            {  
                addedge(bb[i][0],bb[i][1],1);  
                addedge(bb[i][1],bb[i][0],1);  
            }  
            spfa(1,n);  
            printf("%d %d\n",x,m-dist[n]);  
        }  
        return 0;  
    }  



23、次小生成树(秦始皇)

hdu4081Qin Shi Huang's National Road System【次小生成树】

说题意:秦始皇统一中国之后要在全国修公路连接各个城市,抠门皇帝只想修成最小生成树(距离最小,不考虑人力),一个道士说自己可以不花人力物力修一条路,经过两方妥协,选择max(两个城市人口/生成树长度-这条路的长度)的路让他变,求这个比值最大值。

这个题没问次小生成树的值,但是用到了路径最长边这个数组,我叫他Max[][],题中问的是(两个城市人口/生成树长度-这条路的长度),我们首先考虑分母最小,因为对于某个边来说分子是定值啊,分母分成两种情况:1.这个边是最小生成树上的,那啥也别说,mst-cost[][]即可 2.这条边不在最小生成树上:那就是含有这个边的某个生成树,(这么说来这个题应该归纳到次小生成树啊==),mst-Max+cost即可

  1. #include <iostream>    
  2. #include<cstdio>    
  3. #include<cstring>    
  4. #include<cmath>    
  5. using namespace std;    
  6. const int maxn=1010;    
  7. const int inf=0x3f3f3f3f;    
  8. bool vis[maxn],used[maxn][maxn];    
  9. double lowc[maxn];    
  10. int pre[maxn];    
  11. double Max[maxn][maxn],cost[maxn][maxn];    
  12. struct node    
  13. {    
  14.     int x,y,pop;    
  15. }num[1010];    
  16. double min(double a,double b){if(a<b) return a;return b;}    
  17. double max(double a,double b){if(a>b) return a;return b;}    
  18. inline double Dist(node v1,node v2)    
  19. {    
  20.     return sqrt(double(v1.x-v2.x)*(v1.x-v2.x)+double(v1.y-v2.y)*(v1.y-v2.y));    
  21. }    
  22. double prim(int n)    
  23. {    
  24.     double ans=0;    
  25.     memset(vis,false,sizeof(vis));    
  26.     memset(Max,0,sizeof(Max));    
  27.     memset(used,false,sizeof(used));    
  28.     vis[0]=true;    
  29.     pre[0]=-1;    
  30.     for(int i=0;i<n;i++)    
  31.     {    
  32.         lowc[i]=cost[0][i];    
  33.         pre[i]=0;    
  34.     }    
  35.   //  lowc[0]=0.0;    
  36.     for(int i=1;i<n;i++)    
  37.     {    
  38.         double minc=1.0*inf;    
  39.         int p=-1;    
  40.         for(int j=0;j<n;j++)    
  41.             if(!vis[j]&&(minc>lowc[j]||p==-1))    
  42.             {    
  43.                 minc=lowc[j];    
  44.                 p=j;    
  45.             }    
  46.         ans+=minc;    
  47.         vis[p]=true;    
  48.         used[p][pre[p]]=used[pre[p]][p]=true;    
  49.         for(int j=0;j<n;j++)    
  50.         {    
  51.             if(vis[j]&&j!=p)//j!=p必须加!!1    
  52.                 Max[j][p]=Max[p][j]=max(Max[j][pre[p]],lowc[p]);    
  53.             if(!vis[j]&&lowc[j]>cost[p][j])    
  54.             {    
  55.                 lowc[j]=cost[p][j];    
  56.                 pre[j]=p;    
  57.             }    
  58.         }    
  59.     }    
  60.     return ans;    
  61. }    
  62. int main()    
  63. {    
  64.     //freopen("cin.txt","r",stdin);    
  65.     int t,n;    
  66.     scanf("%d",&t);    
  67.     while(t--)    
  68.     {    
  69.         scanf("%d",&n);    
  70.         for(int i=0;i<n;i++) scanf("%d%d%d",&num[i].x,&num[i].y,&num[i].pop);    
  71.         for(int i=0;i<n;i++)    
  72.             for(int j=i+1;j<n;j++)    
  73.                 cost[i][j]=cost[j][i]=Dist(num[i],num[j]);    
  74.         double mst=prim(n);    
  75.        // double mst=smst(n,ans);    
  76.         double ans=-1;    
  77.         for(int i=0;i<n;i++)    
  78.             for(int j=i+1;j<n;j++)    
  79.             {    
  80.                 if(used[i][j])//on mst    
  81.                     ans=max(ans,1.0*(num[i].pop+num[j].pop)/(mst-cost[i][j]));    
  82.                 else    
  83.                     ans=max(ans,1.0*(num[i].pop+num[j].pop)/(mst-Max[i][j]));    
  84.             }    
  85.         printf("%.2f\n",ans);    
  86.     }    
  87.     return 0;    
  88. }    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值