• HDU4370:0 or 1(最短路)


    0 or 1

    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4370

    Description:

    Given a n*n matrix Cij (1<=i,j<=n),We want to find a n*n matrix Xij (1<=i,j<=n),which is 0 or 1.

    Besides,Xij meets the following conditions:

    1.X12+X13+...X1n=1
    2.X1n+X2n+...Xn-1n=1
    3.for each i (1<i<n), satisfies ∑Xki (1<=k<=n)=∑Xij (1<=j<=n).

    For example, if n=4,we can get the following equality:

    X12+X13+X14=1
    X14+X24+X34=1
    X12+X22+X32+X42=X21+X22+X23+X24
    X13+X23+X33+X43=X31+X32+X33+X34

    Now ,we want to know the minimum of ∑Cij*Xij(1<=i,j<=n) you can get.

    Input:

    The input consists of multiple test cases (less than 35 case).
    For each test case ,the first line contains one integer n (1<n<=300).
    The next n lines, for each lines, each of which contains n integers, illustrating the matrix C, The j-th integer on i-th line is Cij(0<=Cij<=100000).

    Output:

    For each case, output the minimum of ∑Cij*Xij you can get.

    Sample Input:

    4 1 2 4 10 2 0 1 1 2 2 0 5 6 3 1 2

    Sample Output:

    3

    Hint:

    For sample, X12=X24=1,all other Xij is 0.

    题意:

    给出一个s矩阵,每个位置都有对应的权值,然后要求你构造一个X矩阵,满足一下条件:

    1.X12+X13+...+X1n = 1;

    2.X1n+X2n+...+Xn-1n = 1;

    3.当1<i<n时,∑Xki (1<=k<=n)=∑Xij (1<=j<=n)。

    问在满足以上条件的情况下,∑Cij*Xij(1<=i,j<=n)的最小值为多少?

    题解:

    orz神题...十分巧妙。

    主要的思路就是将我们构造的X矩阵当作邻接矩阵就行了,对应位置为1则代表对应的行和列之间有连一条边。

    那么根据条件我们知道:1号点只有一个出度,n号点只有一个入度,且2~n-1号点入度出度相等。

    想到这里了之后,还要想两种情况:第1种是从1号点出发直接到n号点,中间每个点的出入度相等;第2种是从1号点出发然后形成一个环最后回到1号点,对于n号点也同理。

    对于第一种情况很好求解,直接跑次spfa就行了,注意下对应边的权值,就为S数组里面的权值。

    对于第二种情况,从1和n出发跑两次spfa,然后在spfa里面加个判断就ok了。

    两种的spfa可以合并一下,本题就解完了~

    代码如下:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <cmath>
    #include <queue>
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int N = 305;
    int n,tot,mn;;
    int vis[N],head[N],c[N][N],d[N];
    struct Edge{
        int v,w,next;
    }e[N*N<<1];
    void adde(int u,int v,int w){
        e[tot].v=v;e[tot].w=w;e[tot].next=head[u];head[u]=tot++;
    }
    void spfa(int s){
        memset(vis,0,sizeof(vis));
        queue<int> q;q.push(s);vis[s]=1;
        memset(d,INF,sizeof(d));d[s]=0;
        while(!q.empty()){
            int u=q.front();q.pop();vis[u]=0;
            for(int i=head[u];i!=-1;i=e[i].next){
                int v=e[i].v;
                if(d[v]>d[u]+e[i].w){
                    d[v]=d[u]+e[i].w;
                    if(!vis[v]){
                        vis[v]=1;
                        q.push(v);
                    }
                }
                if(v==s){
                    mn=min(mn,d[u]+e[i].w);
                }
            }
        }
        return ;
    }
    int main(){
        while(scanf("%d",&n)!=EOF){
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    scanf("%d",&c[i][j]);
            memset(head,-1,sizeof(head));tot=0;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    if(i==j) continue ;
                    adde(i,j,c[i][j]);
                }
            }
            mn=INF;
            spfa(1);
            int tmp=mn,ans=INF;
            mn=INF;
            ans=d[n];
            spfa(n);
            ans=min(ans,mn+tmp);
            cout<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    面向接口编程详解(二)——编程实例
    面向接口编程详解(一)——思想基础
    设计模式之面向接口编程
    EF数据注解
    很多人不知道可以使用这种 key 的方式来对 Vue 组件时行重新渲染
    这是最新的一波Vue实战技巧,不用则已,一用惊人
    Node.js 进阶-你应该知道的 npm 知识都在这
    Vue响应式原理
    eslint规则
    简述vue-cli中chainWebpack的使用方法
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10332386.html
Copyright © 2020-2023  润新知