zoukankan      html  css  js  c++  java
  • bzoj 1774: [Usaco2009 Dec]Toll 过路费【排序+Floyd】

    非常迷的一道题啊
    我觉得挺对的版本只得了30
    总之就是Floyd·改,开两个数组,一个是d[i][j]就是普通的只有边权的最短路,a[i][j]是题目要求的那种
    具体改的地方是把枚举中转点的地方把中转点按从小到大的顺序枚举,d[i][j]按照套路更新即可,然后a[i][j]从a[i][j]原数和d[i][j]+max(c[i],c[j],c[中转点])中取min
    证明的话是最短路不一定是最终答案,能更新这个答案的一定是最大点更小一些的另一条路,所以按点权顺序更新能保证把这种情况全部更新

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=255,inf=1e9+7;
    int n,m,q,a[N][N],d[N][N],v[N];
    struct qwe
    {
    	int p,v;
    }c[N];
    bool cmp(const qwe &x,const qwe &y)
    {
    	return x.v<y.v;
    }
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    int main()
    {
    	n=read(),m=read(),q=read();
    	for(int i=1;i<=n;i++)
    		v[i]=d[i][i]=a[i][i]=c[i].v=read(),c[i].p=i;
    	sort(c+1,c+1+n,cmp);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    			if(i!=j)
    				a[i][j]=d[i][j]=inf;
    	for(int i=1;i<=m;i++)
    	{
    		int x=read(),y=read(),z=read();
    		d[x][y]=d[y][x]=min(d[x][y],z);
    	}
    	for(int k=1;k<=n;k++)
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=n;j++)
    				d[i][j]=min(d[i][j],d[i][c[k].p]+d[c[k].p][j]),a[i][j]=min(a[i][j],d[i][j]+max(max(v[i],v[j]),c[k].v));
    	while(q--)
    	{
    		int x=read(),y=read();
    		printf("%d
    ",a[x][y]);
    	}
    	return 0;
    }
    

    我觉得挺对的版本:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=255,inf=1e9+7;
    int n,m,q,a[N][N],c[N],mx[N][N];
    int read()
    {
        int r=0,f=1;
        char p=getchar();
        while(p>'9'||p<'0')
        {
            if(p=='-')
                f=-1;
            p=getchar();
        }
        while(p>='0'&&p<='9')
        {
            r=r*10+p-48;
            p=getchar();
        }
        return r*f;
    }
    int main()
    {
        n=read(),m=read(),q=read();
        for(int i=1;i<=n;i++)
            c[i]=read(),mx[i][i]=a[i][i]=c[i];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(i!=j)
                    a[i][j]=mx[i][j]=inf;
        for(int i=1;i<=m;i++)
        {
            int x=read(),y=read(),z=read();
            if(a[x][y]>z+max(c[x],c[y]))
                a[x][y]=a[y][x]=z+max(c[x],c[y]),mx[x][y]=mx[y][x]=max(c[x],c[y]);
        }
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    if(a[i][j]>a[i][k]-mx[i][k]+a[k][j]-mx[k][j]+max(mx[i][k],mx[k][j]))
                        a[i][j]=a[i][k]-mx[i][k]+a[k][j]-mx[k][j]+max(mx[i][k],mx[k][j]),mx[i][j]=max(mx[i][k],mx[k][j]);
        while(q--)
        {
            int x=read(),y=read();
            printf("%d
    ",a[x][y]);
        }
        return 0;
    }
    
  • 相关阅读:
    23种设计模式之责任链模式
    23种设计模式之中介者模式
    23种设计模式之代理模式
    23种设计模式之原型模式
    23种设计模式之模板方法模式
    23种设计模式之建造者模式
    23中设计模式之抽象工厂模式
    批处理产生001到999之间的数字
    批处理随机显示星期几
    批处理简易密码登录
  • 原文地址:https://www.cnblogs.com/lokiii/p/9254897.html
Copyright © 2011-2022 走看看