zoukankan      html  css  js  c++  java
  • [kuangbin带你飞]专题四 最短路练习

    小结:

    1,求1到其他点的最短路,和其他点到1的最短路,只需要反边即可。

    2. 最短路维护边可以加,有时乘也是更新可以最短路的。

    3,spfa判负圈只需要判断一个点入队次数>n,那么必有负圈。

    4.如果对最短路更新进行了限制,那么不要直接更新,打上标记之后更新。

    5.最短路可以抽象为01规划,每个边可以取,可以不取。

    6.传递闭包往往会很像拓扑。

    7.必要时把边权压成点权,边和边之间可能也会有权。

    A - Til the Cows Come Home

     POJ - 2387 

    板题:

    #include<cstdio>
    #include<vector>
    #include<queue>
    using namespace std;
    #define pb push_back
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const int maxn=1e3+5;
    int n,m;
    struct edge{int v,w;edge(int a,int b){v=a,w=b;}};
    struct node{
        int id,dis;
        node(int a,int b){id=a,dis=b;}
        friend bool operator<(node a,node b){
        return a.dis>b.dis;
        }
    };
    vector<edge>e[maxn];
    int dis[maxn];
    bool done[maxn];
    void dijkstra(){
        int s=1;
        for(int i=0;i<=n;i++)dis[i]=inf,done[i]=0;
        dis[s]=0;
        priority_queue<node>Q;
        Q.push(node(s,0));
        while(!Q.empty()){
        node u=Q.top();Q.pop();
        if(done[u.id])continue;
        done[u.id]=1;
        for(int i=0;i<e[u.id].size();i++){
        edge y=e[u.id][i];
        if(done[y.v])continue;
        if(dis[y.v]>y.w+dis[u.id]){
        dis[y.v]=y.w+u.dis;
        Q.push(node(y.v,dis[y.v]));
        }
        }
        }
    }
    int main(){
        int t;
        scanf("%d %d",&t,&n);
        for(int i=1,u,v,w;i<=t;i++){
        scanf("%d %d %d",&u,&v,&w);
        e[u].pb(edge(v,w));
        e[v].pb(edge(u,w));
        }
        dijkstra();
        printf("%d
    ",dis[n]);
        // system("pause");
        return 0;
    }
    View Code

    B - Frogger

     POJ - 2253 

    无法优化,构建图的复杂度都是O(N*N)的,上floyd

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++)
    #define per(i,j,k) for(int i=(int)k;i>=(int)j;i--)
    #define pb push_back
    typedef double db;
    const int maxn=2e2+5;
    struct point{db x,y;}P[maxn];
    db dis(point a,point b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
    db gp[maxn][maxn];
    int main(){
        int n,cas=0;
        while(~scanf("%d",&n),n){
        for(int i=1;i<=n;i++)scanf("%lf %lf",&P[i].x,&P[i].y);
        // db ans=dis(P[1],P[2]);
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        gp[i][j]=dis(P[i],P[j]);
        for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        gp[i][j]=min(gp[i][j],max(gp[i][k],gp[k][j]));
        db ans=gp[1][2];
        printf("Scenario #%d
    ",++cas);
        printf("Frog Distance = %.3lf
    
    ",ans);
        }
        // system("pause");
        return 0;
    }
    View Code

    C - Heavy Transportation

     POJ - 1797 

    就是说1到n有多条路,每一条路权值必然由最小边决定,问你那条路权值最大。

    两种做法:

    1.最大生成树:
    将边按照由大到小排序,不断加边,如果突然加入一条边1,到n联通了,说明这个就是答案。

    这样保证了路径的权值由最小值决定,而且保证了最小值最大化。因为其他连边必然比当前ans小。

     1 #include<cstdio>
     2 #include<vector>
     3 #include<queue>
     4 #include<algorithm>
     5 using namespace std;
     6 #define pb push_back
     7 typedef long long ll;
     8 const int inf=0x3f3f3f3f;
     9 const int maxn=1e3+5;
    10 int n,m;
    11 int fa[maxn];
    12 struct edge{int u,v,w;edge(int a,int b,int x){u=a,v=b,w=x;}};
    13 vector<edge>e;
    14 bool cmp(edge a,edge b){return a.w>b.w;}
    15 void init(){for(int i=1;i<=maxn;i++)fa[i]=i;}
    16 int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    17 void build(int x,int y){int dx=find(x),dy=find(y);if(dx!=dy)fa[dx]=dy;}
    18 int main(){
    19     int t,cas=0;
    20     scanf("%d",&t);
    21     while(t--){
    22     e.clear();
    23     scanf("%d %d",&n,&m);
    24     for(int i=1;i<=n;i++)fa[i]=i;
    25     for(int i=1,u,v,w;i<=m;i++){
    26     scanf("%d %d %d",&u,&v,&w);
    27     e.pb(edge(u,v,w));
    28     }
    29     sort(e.begin(),e.end(),cmp);
    30     int ans=0;
    31     for(int i=0;i<e.size();i++){
    32     build(e[i].v,e[i].u);
    33     if(find(1)==find(n)){ans=e[i].w;break;}
    34     }
    35     printf("Scenario #%d:
    ",++cas);
    36     printf("%d
    
    ",ans);
    37     }
    38     // system("pause");
    39     return 0;
    40 }
    View Code

    2.最短路维护:
    dis不再表示最短路,而表示某个点到源点路径的权值。

    那么必然有:dis[v]<min(dis[u],w) 的更新条件,求最大权值,初始化为0而非inf,不断更新路径上的最小边,使其最大。

     1 #include<cstdio>
     2 #include<vector>
     3 #include<queue>
     4 #include<algorithm>
     5 using namespace std;
     6 #define pb push_back
     7 typedef long long ll;
     8 const int inf=0x3f3f3f3f;
     9 const int N=1e5+5;
    10 struct edge{int v,w;edge(int a,int b){v=a,w=b;}};
    11 vector<edge>e[N];
    12 int n,m;
    13 int dis[N];
    14 bool inq[N];
    15 void spfa(int s){
    16     for(int i=1;i<=n;i++)dis[i]=0,inq[i]=0;
    17     dis[s]=inf;
    18     queue<int>Q;
    19     Q.push(s);inq[s]=1;
    20     while(!Q.empty()){
    21     int u=Q.front();Q.pop();inq[u]=0;
    22     for(int i=0;i<e[u].size();i++){
    23         int v=e[u][i].v,w=e[u][i].w;
    24     if(dis[v]<min(dis[u],w)){
    25     dis[v]=min(dis[u],w);
    26     if(!inq[v])Q.push(v),inq[v]=1;
    27     }
    28     }
    29     }
    30 }
    31 int main(){
    32     int t,cas=0;
    33     scanf("%d",&t);
    34     while(t--){
    35     scanf("%d %d",&n,&m);
    36     for(int i=1;i<=n;i++)e[i].clear();
    37     for(int i=1,u,v,w;i<=m;i++){
    38     scanf("%d %d %d",&u,&v,&w);
    39     e[u].pb(edge(v,w));
    40     e[v].pb(edge(u,w));
    41     }
    42     spfa(1);
    43     printf("Scenario #%d:
    ",++cas);
    44     printf("%d
    
    ",dis[n]);
    45     }
    46     // system("pause");
    47     return 0;
    48 }
    View Code

    D - Silver Cow Party

     POJ - 3268 

    无脑题;

    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<algorithm>
    using namespace std;
    #define pb push_back
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const int N=1e5+5;
    struct edge{int v,w;edge(int a,int b){v=a,w=b;}};
    vector<edge>e[N];
    int n,m;
    int dis[N];
    bool inq[N];
    void spfa(int s){
        for(int i=1;i<=n;i++)dis[i]=inf,inq[i]=0;
        dis[s]=0;
        queue<int>Q;
        Q.push(s);inq[s]=1;
        while(!Q.empty()){
        int u=Q.front();Q.pop();inq[u]=0;
        for(int i=0;i<e[u].size();i++){
            int v=e[u][i].v,w=e[u][i].w;
        if(dis[v]>dis[u]+w){
        dis[v]=dis[u]+w;
        if(!inq[v])Q.push(v),inq[v]=1;
        }
        }
        }
    }
    int a[N];
    int main(){
        int x;
        scanf("%d %d %d",&n,&m,&x);
        // for(int i=1;i<=n;i++)e[i].clear();
        for(int i=1,u,v,w;i<=m;i++){
        scanf("%d %d %d",&u,&v,&w);
        e[u].pb(edge(v,w));
        }
        spfa(x);
        for(int i=1;i<=n;i++)a[i]=dis[i];
        for(int i=1;i<=n;i++)        
        if(i!=x)spfa(i),a[i]+=dis[x];
        int ans=*max_element(a+1,a+1+n);
        printf("%d
    ",ans);
        // }
        // system("pause");
        return 0;
    }
    View Code

    E - Currency Exchange

     POJ - 1860 

    就是说n种货币,可以相互交换,问你能不能交换过程中把钱变多。

    如果钱变多,说明有正圈,陷在正圈里不出来,肯定一直变多。直接判正圈。

    如果说一个点入队次数大于n,说明有正圈。

    注意蛋疼的精度,eps设大了不行。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<map>
     4 #include<vector>
     5 #include<string>
     6 #include<cstring>
     7 #include<queue>
     8 using namespace std;
     9 #define pb push_back
    10 const int inf=0x3f3f3f3f;
    11 struct edge{int v;double r,c;edge(int x,double y,double z){v=x,r=y,c=z;}};
    12 const int N=1e2+5;  
    13 const double eps=1e-10;
    14 vector<edge>e[N];
    15 int n,m,s;
    16 double V;
    17 bool flag;
    18 bool inq[N];int cnt[N];
    19 double dis[N];
    20 void spfa(){
    21     for(int i=1;i<=n;i++)cnt[i]=0,inq[i]=0,dis[i]=0.0;
    22     queue<int>Q;
    23     Q.push(s);inq[s]=1;dis[s]=V;
    24     while(!Q.empty()){
    25         int u=Q.front();Q.pop();inq[u]=0;
    26         for(int i=0;i<e[u].size();i++){
    27             int v=e[u][i].v;double r=e[u][i].r,c=e[u][i].c;
    28             double val=(dis[u]-c)*r;
    29             if(dis[v]<val){
    30                 dis[v]=val;
    31                 if(inq[v])continue;
    32                 Q.push(v),inq[v]=1,++cnt[v];
    33                 if(cnt[v]>n){flag=1;return ;}
    34             }
    35         }
    36     }
    37     // return 0;
    38 }
    39 int main(){
    40     double Rab,Cab,Rba,Cba;
    41     scanf("%d %d %d %lf",&n,&m,&s,&V);
    42     for(int i=1,u,v;i<=m;i++){
    43         scanf("%d %d %lf %lf %lf %lf",&u,&v,&Rab,&Cab,&Rba,&Cba);
    44         e[u].pb(edge(v,Rab,Cab));
    45         e[v].pb(edge(u,Rba,Cba));
    46     }
    47     flag=0;
    48     spfa();
    49     if(flag)puts("YES");
    50     else puts("NO");
    51     // system("pause");
    52     return 0;
    53 }
    View Code

    F - Wormholes

     POJ - 3259 

    直接spfa判负圈。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<map>
     4 #include<vector>
     5 #include<string>
     6 #include<cstring>
     7 #include<queue>
     8 using namespace std;
     9 #define pb push_back
    10 const int inf=0x3f3f3f3f;
    11 const int N=6e2+5;  
    12 const double eps=1e-10;
    13 struct edge{int v,w;edge(int a,int b){v=a,w=b;}};
    14 vector<edge>e[N];
    15 int n,m,W;
    16 bool flag;
    17 bool inq[N];
    18 int dis[N];
    19 int cnt[N];
    20 void spfa(){
    21     for(int i=1;i<=n;i++)inq[i]=0,cnt[i]=0,dis[i]=inf;
    22     queue<int>Q;
    23     Q.push(1),inq[1]=1;dis[1]=0;
    24     while(!Q.empty()){
    25         int u=Q.front();Q.pop();inq[u]=0;
    26         for(int i=0;i<e[u].size();i++){
    27             int v=e[u][i].v,w=e[u][i].w;
    28             if(dis[v]>dis[u]+w){
    29             dis[v]=dis[u]+w;
    30             if(inq[v])continue;
    31             Q.push(v),inq[v]=1,++cnt[v];
    32             if(cnt[v]>n){flag=1;return ;}
    33             }
    34         }
    35     }
    36 }
    37 int main(){
    38     int T;scanf("%d",&T);
    39     while(T--){
    40         scanf("%d %d %d",&n,&m,&W);
    41         for(int i=1;i<=n;i++)e[i].clear();
    42         for(int i=1,u,v,w;i<=m;i++){
    43         scanf("%d %d %d",&u,&v,&w);
    44         e[u].pb(edge(v,w));
    45         e[v].pb(edge(u,w));
    46         }
    47         for(int i=1,u,v,w;i<=W;i++){
    48         scanf("%d %d %d",&u,&v,&w);
    49         e[u].pb(edge(v,-w));
    50         }
    51         flag=0;
    52         spfa();
    53         // cout<<"test"<<endl;
    54         // for(int i=1;i<=n;i++)cout<<i<<" "<<dis[i]<<endl; 
    55         // cout<<"test "<<dis[1]<<endl;
    56         if(flag)puts("YES");
    57         else puts("NO");
    58     }    
    59     // system("pause");
    60     return 0;
    61 }
    View Code

    G - MPI Maelstrom

     POJ - 1502 

    无脑;

    #include<cstdio>
    #include<iostream>
    #include<map>
    #include<vector>
    #include<string>
    #include<cstring>
    #include<queue>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    #define pb push_back
    const int inf=0x3f3f3f3f;
    const int N=1e2+5;
    int gp[N][N];
    int n;
    void floyd(){
        for(int k=1;k<=n;k++){
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                // gp[i][j]=min(gp[i][j])
                if(gp[i][j]>gp[i][k]+gp[k][j])
                gp[i][j]=gp[i][k]+gp[k][j];
                }
            }
        }
    }
    char s[1000];
    int main(){
        while(~scanf("%d",&n)){
        memset(gp,0,sizeof gp);
        for(int i=1;i<=n;i++)gp[i][i]=0;
        for(int i=2;i<=n;i++){
            for(int j=1;j<=i-1;j++){
                scanf("%s",s);
                int a;
                if(s[0]=='x')a=inf;
                else  a=atoi(s);
            gp[j][i]=gp[i][j]=a;
            }
        }
        floyd();
        // int ans= * max_element(gp+1+n,gp+n*n);
        int ans=0;
        for(int i=1;i<=n;i++){
            // for(int j=1;j<=n;j++){
                if(gp[1][i]!=inf)ans=max(ans,gp[1][i]);
            // }
        }   
        printf("%d
    ",ans);
        }
        // system("pause");
        return 0;
    }
    View Code

    H - Cow Contest

     POJ - 3660 

    就是说n个人之间有着相互关系,问你能有几个确定排名。

    开始自然想拓扑,但不好解决。

    考虑传递闭包,如果a比b牛逼,b比c牛逼,那么a比c牛逼。

    如果说一个点,和其他n-1个点关系明确,那么这个点就是明确的。

    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    #define pb push_back
    const int inf=0x3f3f3f3f;
    const ll mod=1e9+7;
    const int N=1e2+6;
    int gp[N][N];
        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++){
                    gp[i][j]|=(gp[i][k])&(gp[k][j]);
                }
            }
        }
    }
    int main(){
        scanf("%d %d",&n,&m);
        memset(gp,0,sizeof gp);
        for(int i=1,u,v;i<=m;i++){
            scanf("%d %d",&u,&v);
        gp[u][v]=1;
        }
        floyd();
        int ans=0;
        for(int i=1;i<=n;i++){
            int sum=0;
            for(int j=1;j<=n;j++){
                if(gp[i][j]||gp[j][i])sum++;
            }
            if(sum==n-1)ans++;
        }
        printf("%d
    ",ans);
        // for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    
    
    
        // system("pause");
        return 0;
    }
    View Code

    I - Arbitrage

     POJ - 2240 

    套利:就是说一个货币,和其他货币不断交换后,最后变多了。问你有没有套利。

    开始想dfs,感觉没啥毛病,但就是不对。

    考虑最短路维护最大的交换钱,最后判断dis[1]即可。

    #include<cstdio>
    #include<iostream>
    #include<map>
    #include<vector>
    #include<string>
    #include<cstring>
    using namespace std;
    const int N=1e2+5;
    #define pb push_back
    char s[N][N],s1[N],s2[N];
    const double eps=1e-8;
    int n,m;
    double gp[N][N];
    void floyd(){
        for(int k=1;k<=n;k++){
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                if(gp[i][j]<gp[i][k]*gp[k][j])
                gp[i][j]=gp[i][k]*gp[k][j];
                }
            }
        }
    }
    map<string,int>mp;
    int main(){
        int cas=0;
        while(~scanf("%d",&n),n){
            mp.clear();
            for(int i=1;i<=n;i++)scanf("%s",s[i]),mp[ s[i] ]=i,gp[i][i]=1.0;
            memset(gp,1,sizeof gp);
            scanf("%d",&m);
            for(int i=1,u,v;i<=m;i++){
                double w;
                scanf("%s %lf %s",s1,&w,s2);
                // cout<<"test :"<<s1<<" "<<s2<<endl;
                u=mp[s1];v=mp[s2];
                gp[u][v]=w;
            }
            floyd();
            // for(int i=1;i<=n;i++){
            //     for(int j=1;j<=n;j++){
            //         cout<<i<<" "<<j<<" "<<gp[i][j]<<endl;
            //     }
            // }
            bool flag=0;
            for(int i=1;i<=n;i++){
                if(gp[i][i]>1){flag=1;break;}
            }
    
            printf("Case %d: ",++cas);
            if(flag)puts("Yes");
            else puts("No");
        }
        // system("paus?e");// bool vis[N],flag;
        return 0;
    
    }
    // 3
    // USDollar
    // BritishPound
    // FrenchFranc
    // 3
    // USDollar 0.5 BritishPound
    // BritishPound 10.0 FrenchFranc
    // Frenc0hFranc 0.21 USDollar
    
    // 3
    // USDollar
    // BritishPound
    // FrenchFranc
    // 6
    // USDollar 0.5 BritishPound
    // USDollar 4.9 FrenchFranc
    // BritishPound 10.0 FrenchFranc
    // BritishPound 1.99 USDollar
    // FrenchFranc 0.09 BritishPound
    // FrenchFranc 0.19 USDollar
    
    // 0
    View Code

    J - Invitation Cards

     POJ - 1511 

    题意:求1到其他点的最短路和,以及其他点到1点最短路之和,

    直接无脑跑是不行的,寻求问题转化。

    就是说要找其他点到1点的最短路,把边反过来更新。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<map>
     4 #include<vector>
     5 #include<string>
     6 #include<cstring>
     7 #include<queue>
     8 #include<cstdlib>
     9 #include<algorithm>
    10 using namespace std;
    11 #define pb push_back
    12 #define fi first
    13 #define se second
    14 typedef long long ll;
    15 const int inf=0x3f3f3f3f;
    16 const int N=1e6+5;
    17 int n,m;
    18 struct edge{int v;ll w;edge(int a,long long  b){v=a;w=b;}};
    19 vector<edge>e[N];
    20 struct mp{int x,y;long long z;};
    21 vector<mp>maps;
    22 ll ans;
    23 long long dis[N];
    24 bool inq[N];
    25 void spfa(){
    26     for(int i=1;i<=n;i++)dis[i]=inf,inq[i]=0;
    27     queue<int>Q;
    28     Q.push(1),inq[1]=1,dis[1]=0;
    29     while(!Q.empty()){
    30         int u=Q.front();Q.pop();inq[u]=0;
    31         for(int i=0;i<e[u].size();i++){
    32             int v=e[u][i].v;long long w=e[u][i].w;
    33             if(dis[v]>dis[u]+w){
    34             dis[v]=dis[u]+w;
    35             if(!inq[v])Q.push(v),inq[v]=1;
    36         }
    37     }
    38     }
    39     for(int i=1;i<=n;i++)ans+=dis[i];
    40 }
    41 int main(){
    42     int T;scanf("%d",&T);
    43     while(T--){
    44     scanf("%d %d",&n,&m);
    45     maps.clear();
    46     ans=0;
    47     int u,v;ll w;
    48     for(int i=1;i<=n;i++)e[i].clear();
    49     for(int i=1;i<=m;i++){
    50     mp tmp;
    51     scanf("%d %d %lld",&tmp.x,&tmp.y,&tmp.z);
    52     maps.pb(tmp);
    53     }
    54     for(int i=0;i<m;i++){
    55         int u=maps[i].x,v=maps[i].y;long long w=maps[i].z;
    56         e[u].pb(edge(v,w));
    57     }
    58     spfa();
    59     for(int i=1;i<=n;i++)e[i].clear();
    60     for(int i=0;i<m;i++){
    61         int u=maps[i].x,v=maps[i].y;long long w=maps[i].z;
    62         e[v].pb(edge(u,w));
    63     }
    64     spfa();
    65     printf("%lld
    ",ans);
    66     }
    67     // system("pause");
    68     return 0;
    69 }
    View Code

     K:

    裸的差分约束,long long 数据。

    #include<cstdio>
    #include<iostream>
    #include<map>
    #include<vector>
    #include<string>
    #include<cstring>
    #include<queue>
    // #include<cstdlib>
    #include<algorithm>
    using namespace std;
    #define pb push_back
    #define fi first
    #define se second
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const int N=3e4+5;
    // int n,m;
    // [N];
    // void spfa(){
    //     for(int i=1;i<=n;i++)inq[i]=0,dis[i]=inf;
    //     queue<int>Q;
    //     Q.push(1);inq[1]=1;dis[1]=0;
    //     while(!Q.empty()){
    //         int u=Q.front();Q.pop();inq[u]=0;
    //         for(int i=0;i<e[u].size();i++){
    //             int v=e[u][i].v,w=e[u][i].w;
    //             if(dis[v]>dis[u]+w){
    //                 dis[v]=dis[u]+w;
    //                 if(!inq[v])Q.push(v),inq[v]=1;
    //             }
    //         }
    //     }
    // }
    int head[N],cnt;//cnt main里初始化为0,head main初始化为-1
    struct edge{int to,w,next;}e[N*10];//注意有重边,乘10
    struct node{int id,dis;//id点,dis距离
        node(int x,int y){id=x,dis=y;}
        friend bool operator<(node a,node b){
        return a.dis>b.dis;//距离小的出队
        }
    };
    void add(int u,int v,int w){//加边
        e[cnt].to=v,e[cnt].w=w,e[cnt].next=head[u],head[u]=cnt++;
    }
    int dis[N];
    bool done[N];//dis记录距离,done记录是否找到最短路
    int n,m;
    void dijkstra(){
        int s=1;//s起点 视情况调整
        for(int i=1;i<=N;i++)dis[i]=inf,done[i]=0;
        dis[s]=0;
        priority_queue<node>Q;
        Q.push(node(s,0));
        while(!Q.empty()){
        int x=Q.top().id;
        Q.pop();
        if(done[x])continue;
        done[x]=1;
        for(int i=head[x];i!=-1;i=e[i].next){
        int y=e[i].to;
        if(done[y])continue;
        if(dis[y]>dis[x]+e[i].w)dis[y]=dis[x]+e[i].w;//更新距离
        Q.push(node(y,dis[y]));
        }
        }
    }
    int main(){
        memset(head,-1,sizeof head);
        scanf("%d %d",&n,&m);
        for(int i=1,u,v,w;i<=m;i++){
            scanf("%d %d %d",&u,&v,&w);
            // e[u].pb(edge(v,w));
            add(u,v,w);
        }
        dijkstra();
        // int ans= * max_element(dis+1,dis+1+n);
        int ans=0;
        for(int i=1;i<=n;i++)ans=max(ans,dis[i]);
        printf("%d
    ",ans);
        // system("pause");
        return 0;
    }
    View Code

    L:傻逼题,样例都没法测

    M - 昂贵的聘礼

     POJ - 1062 

    解法:挺简单的,就是没考虑限制,按照区间进行枚举即可,蛋疼的g++过不了。

    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<iostream>
    #include<cstring>
    using namespace std;
    const int N=1e2+5;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    #define pb push_back
    int n,m;
    int  gp[N][N];
    int  lim[N];
    int val[N],dis[N];bool inq[N],can[N];
    int spfa(){
        for(int i=1;i<=n;i++)inq[i]=0,dis[i]=inf;
        queue<int>Q;
        Q.push(1),inq[1]=1;dis[1]=0;
        while(!Q.empty()){
            int u=Q.front();Q.pop();inq[u]=0;
            for(int i=1;i<=n;i++){
            if(dis[i]>dis[u]+gp[u][i]&&can[i]){
            dis[i]=dis[u]+gp[u][i];
            if(!inq[i])Q.push(i),inq[i]=1;
            }
            }
        }
        int  cur=inf;
        for(int i=1;i<=n;i++){
            cur=min(cur,dis[i]+val[i]);
        }
        return cur;
    }
    int main(){
        scanf("%d %d",&m,&n);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(i==j)gp[i][j]=0;
                else gp[i][j]=inf;
            }
        }
        for(int i=1,q;i<=n;i++){
            scanf("%d %d %d",&val[i],&lim[i],&q);
            for(int j=1,v;j<=q;j++){
                int  w;
                scanf("%d %d",&v,&w);
                // e[i].pb(edge(v,w));
                gp[i][v]=w;
            }
        }
        int  ans=inf;
        for(int i=0;i<=m;i++){
        memset(can,0,sizeof can);
        for(int j=1;j<=n;j++){
        if(lim[j]<=lim[1]+i&&lim[j]>=lim[1]-m+i)can[j]=1;
          // spfa();
        ans=min(ans,spfa() );
        }
        }
        printf("%lld
    ",ans);   
        // system("pause");
        return 0;
    }
    View Code

    R - 0 or 1

     HDU - 4370 

    题意:给你一个矩阵C,让你求一个矩阵01矩阵X,

    满足:.X 12+X 13+...X 1n=1 ,

    X 1n+X 2n+...X n-1n=1

    ∑X ki (1<=k<=n)=∑X ij (1<=j<=n).

    使得

    最小

     

    怎么理解这题呢?想象最短路,到有一条边,表示到有一条有向边,表示这条边是否存在。
    对于条件:点的出度为,点的入度为,其他点入度等于出度。
    那么有两种情况满足:,
    1.   跑一遍到的最短路,满足条件。
    2   1 形成一个环,n 形成一个环,满足条件
    。注意:更新最短路源点不能设为0,而是inf,不然没法更新最短路。
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll MOD=1e9+7;
    #define pb push_back
    const int inf=0x3f3f3f3f;
    int n;
    const int N=3e2+5;
    int dis[N],C[N][N];bool inq[N];
    void spfa(int s){
        for(int i=1;i<=n;i++)inq[i]=0,dis[i]=inf;
        queue<int>Q;Q.push(s);inq[s]=1;
        for(int i=1;i<=n;i++){
            if(i==s)dis[i]=inf;
            else dis[i]=C[s][i],Q.push(i);
        }
        while(!Q.empty()){
            int u=Q.front();Q.pop();inq[u]=0;
            for(int i=1;i<=n;i++){
                if(dis[i]>dis[u]+C[u][i]){
                    dis[i]=dis[u]+C[u][i];
                    if(!inq[i])Q.push(i),inq[i]=1;
                }
            }
        }
    }
    int main(){
        while(~scanf("%d",&n)){
    
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++)
                    scanf("%d",&C[i][j]);
            }
            spfa(1);
            int ans=dis[n];
            int d1=dis[1];
            spfa(n);
            int d2=dis[n];
            ans=min(ans,d1+d2);
            printf("%d
    ",ans);
        }
    
        // system("pause");
        return 0;
    }
    View Code
    想的太多,做的太少;
  • 相关阅读:
    [小知识]如何查看IIS6应用程序池所对应的进程ID
    继续向大家汇报服务器情况
    CNBlogs DotText 1.0 Beta 2 重要更新
    垃圾广告记录
    Firefox 11正式发布
    Firefox 10正式发布
    Firefox 6 正式发布
    Firefox 5 正式发布
    Firefox 9正式发布
    Firefox 8正式发布
  • 原文地址:https://www.cnblogs.com/littlerita/p/12610546.html
Copyright © 2011-2022 走看看