zoukankan      html  css  js  c++  java
  • 7.1 NOI模拟赛 dp floyd

    avatar
    avatar

    这是一道非常垃圾的题目 且 数据范围简直迷惑选手。。

    可以发现 题目中有 边权递增 边的条数 所有边权值不同 最小边权和等条件。

    看起来很难做 一个想法 边权递增+边的1的权值都不相同可以想到 关系存在于边的话应该是一张DAG.

    所以 可以把边化点建图 暴力建图是(n^2)的 采用归并排序+前缀和优化建图就是线性的了。

    然后考虑在这张DAG上搞事情 发现边的条数很难做。

    怎么做都需要一个dp数组(f_{i,j})表示到达i此时经过的路径数为j的最小权值。

    状态数很多 尽管转移可以拓扑排序 那么总复杂度为(Qnm)过不了

    尽管建立除了DAG但是边的条数还是很难解决。

    容易想到状态(f_{i,j,k})表示i到j经过k条边的最小值。

    这道题迷惑的一点是 这个状态是(1e8) 我以为过不了所以就一直在研究怎么在DAG上做。。

    其实这个状态在开(o2)的情况下表现非常优秀 可以通过。

    根据这道题启示我以后(1e8~2e8)的复杂度 大胆莽。

    考虑转移 由于要求边权要求递增所以可以一条边一条边往里面插入。

    实际上只需要更新以这条路径为终点即可。复杂度(mn^2)

    但是这道题数据还是很良心的 我在DAG上跑dfs就有90了。

    code bf:
    //#include<bitsstdc++.h>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #define ll long long
    #define db double
    #define INF 1000000000
    #define ldb long double
    #define pb push_back
    #define put_(x) printf("%d ",x);
    #define get(x) x=read()
    #define gt(x) scanf("%d",&x)
    #define gi(x) scanf("%lf",&x)
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define gc(a) scanf("%s",a+1)
    #define rep(p,n,i) for(RE int i=p;i<=n;++i)
    #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
    #define fep(n,p,i) for(RE int i=n;i>=p;--i)
    #define vep(p,n,i) for(RE int i=p;i<n;++i)
    #define pii pair<int,int>
    #define mk make_pair
    #define RE register
    #define P 1000000007
    #define gf(x) scanf("%lf",&x)
    #define pf(x) ((x)*(x))
    #define uint unsigned long long
    #define ui unsigned
    #define EPS 1e-8
    #define sq sqrt
    #define mod 998244353
    #define S second
    #define F first
    #define op(x) t[x].op
    #define d(x) t[x].d
    #define Set(a,v) memset(a,v,sizeof(a))
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        RE int x=0,f=1;RE char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    const int MAXN=5010<<1,maxn=155;
    int n,m,len,Q,id,mark,ans;
    int s[MAXN],c[MAXN];
    int lin[MAXN],ver[MAXN],nex[MAXN];
    vector<pii>g[maxn],w[maxn];
    struct wy{int x,y;int id;}t[MAXN];
    inline void add(int x,int y)
    {
    	ver[++len]=y;
    	nex[len]=lin[x];
    	lin[x]=len;
    }
    inline void dfs(int x,int res,int v)
    {
    	if(v>=ans)return;
    	if(t[x].y==mark){ans=v;return;}
    	if(!res)return;
    	for(int i=lin[x];i;i=nex[i])dfs(ver[i],res-s[ver[i]],v+c[ver[i]]);
    }
    int main()
    {
    	freopen("ha.in","r",stdin);
    	freopen("ha.out","w",stdout);
    	get(n);get(m);get(Q);
    	rep(1,m,i)
    	{
    		int get(x),get(y),get(z);
    		t[i]=(wy){x,y,z};
    		g[x].pb(mk(z,i));//起点.
    		w[y].pb(mk(z,i));//终点.
    		s[i]=1;c[i]=z;
    	}
    	id=m;
    	//以边化点.
    	rep(1,n,i)
    	{
    		sort(g[i].begin(),g[i].end());
    		sort(w[i].begin(),w[i].end());
    		//归并建图.
    		int k1=g[i].size()-1;
    		int k2=w[i].size()-1;
    		++id;
    		for(int k=1;k<=(int)(g[i].size()+w[i].size());++k)
    		{
    			if(k1==-1)
    			{
    				add(w[i][k2].S,id);
    				--k2;continue;
    			}
    			if(k2==-1){--k1;continue;}
    			if(w[i][k2].F<g[i][k1].F)add(id,g[i][k1].S),--k1;
    			else
    			{
    				add(w[i][k2].S,id);
    				++id;add(id,id-1);--k2;
    			}
    		}
    	}
    	rep(1,Q,i)
    	{
    		int get(a),get(b),get(C);
    		if(a==b){puts("0");continue;}
    		if(!C){puts("-1");continue;}
    		ans=INF;mark=b;
    		vep(0,g[a].size(),j)dfs(g[a][j].S,C-1,c[g[a][j].S]);
    		put(ans==INF?-1:ans);
    	}
    	return 0;
    }
    
    code sol:
    //#include<bitsstdc++.h>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #define ll long long
    #define db double
    #define INF 1000000000
    #define ldb long double
    #define pb push_back
    #define put_(x) printf("%d ",x);
    #define get(x) x=read()
    #define gt(x) scanf("%d",&x)
    #define gi(x) scanf("%lf",&x)
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define gc(a) scanf("%s",a+1)
    #define rep(p,n,i) for(RE int i=p;i<=n;++i)
    #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
    #define fep(n,p,i) for(RE int i=n;i>=p;--i)
    #define vep(p,n,i) for(RE int i=p;i<n;++i)
    #define pii pair<int,int>
    #define mk make_pair
    #define RE register
    #define P 1000000007
    #define gf(x) scanf("%lf",&x)
    #define pf(x) ((x)*(x))
    #define uint unsigned long long
    #define ui unsigned
    #define EPS 1e-8
    #define sq sqrt
    #define mod 998244353
    #define S second
    #define F first
    #define op(x) t[x].op
    #define d(x) t[x].d
    #define Set(a,v) memset(a,v,sizeof(a))
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        RE int x=0,f=1;RE char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    const int MAXN=5010,maxn=155;
    int n,m,len,Q,id,mark,ans;
    struct wy{int x,y,z;}t[MAXN];
    int f[maxn][maxn][maxn];//f[i][j][k]表示由i到j经过了<=k条边的最短路.
    inline int cmp(wy a,wy b){return a.z<b.z;}
    int main()
    {
    	freopen("1.in","r",stdin);
    	//freopen("2.out","w",stdout);
    	get(n);get(m);get(Q);
    	rep(1,m,i)
    	{
    		int get(x),get(y),get(z);
    		t[i]=(wy){x,y,z};
    	}
    	memset(f,0x3f,sizeof(f));
    	sort(t+1,t+1+m,cmp);
    	rep(1,n,i)rep(0,n,k)f[i][i][k]=0;
    	rep(1,m,j)
    	{
    		rep(1,n,i)
    		{
    			rep(1,n,k)
    			{
    				f[i][t[j].y][k]=min(f[i][t[j].y][k],f[i][t[j].x][k-1]+t[j].z);
    			}
    		}
    	}
    	rep(1,Q,i)
    	{
    		int get(x),get(y),get(z);
    		put(f[x][y][min(z,n)]>=INF?-1:f[x][y][min(z,n)]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    io
    api 类库
    文档生成工具
    数据存储
    uml vs2010
    IE,firefox下jquery获取一组checkbox选中值的问题
    如何通过Jquery简单又快速的获取一组radio的取值呢?
    WCF重载的方式
    Jquery文本框赋值
    Jquery以name获取值
  • 原文地址:https://www.cnblogs.com/chdy/p/13221681.html
Copyright © 2011-2022 走看看