• 【求助,待续!】holes


    NOIP模拟赛 虫洞(holes)

    Problem 3 虫洞(holes.cpp/c/pas)

    【题目描述】

    N个虫洞,M条单向跃迁路径。从一个虫洞沿跃迁路径到另一个虫洞需要消耗一定量的燃料和1单位时间。虫洞有白洞和黑洞之分。设一条跃迁路径两端的虫洞质量差为delta。

    1.从白洞跃迁到黑洞,消耗的燃料值减少delta,若该条路径消耗的燃料值变为负数的话,取为0。

    2.从黑洞跃迁到白洞,消耗的燃料值增加delta。

    3.路径两端均为黑洞或白洞,消耗的燃料值不变化。

    作为压轴题,自然不会是如此简单的最短路问题,所以每过1单位时间黑洞变为白洞,白洞变为黑洞。在飞行过程中,可以选择在一个虫洞停留1个单位时间,如果当前为白洞,则不消耗燃料,否则消耗s[i]的燃料。现在请你求出从虫洞1到N最少的燃料消耗,保证一定存在1到N的路线。

    【输入格式】

    第1行:2个正整数N,M

    第2行:N个整数,第i个为0表示虫洞i开始时为白洞,1表示黑洞。

    第3行:N个整数,第i个数表示虫洞i的质量w[i]。

    第4行:N个整数,第i个数表示在虫洞i停留消耗的燃料s[i]。

    第5..M+4行:每行3个整数,u,v,k,表示在没有影响的情况下,从虫洞u到虫洞v需要消耗燃料k。

    【输出格式】

    一个整数,表示最少的燃料消耗。

    【样例输入】

    4 5

    1 0 1 0

    10 10 100 10

    5 20 15 10

    1 2 30

    2 3 40

    1 3 20

    1 4 200

    3 4 200

    【样例输出】

    130

    【数据范围】

    对于30%的数据: 1<=N<=100,1<=M<=500

    对于60%的数据: 1<=N<=1000,1<=M<=5000

    对于100%的数据: 1<=N<=5000,1<=M<=30000

                  其中20%的数据为1<=N<=3000的链
    
                  1<=u,v<=N, 1<=k,w[i],s[i]<=200
    

    【样例说明】

    按照1->3->4的路线。

    根据题意建图,跑一遍spfa完事

    搞成2n个点,前n个白,后n个黑

    对于u,v,k

    颜色一样,add(u,v,k);add(u+n,v+n,k);

    颜色不一样, add(u,v+n,k+);add(u+n,v,k-)

    处理完后,自己的黑白两点相连

    add(i,i+n,s[i]);add(i+n,i,0);

    源点1,若白,spfa(1)
    若黑,spfa(1+n)

    ans=min(dist[n],dist[n*2])

    我的程序怎么了呜呜呜调不出来

    别人AC的程序

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    #define ci const int &
    using namespace std;
    const int N=1000005; 
    int n,m;
    int w[N],s[N],hole[N];
    struct Ed{
    	int to,nxt,dis;
    }ed[N];
    int head[N],ednum;
    void add(ci from,ci to,ci dis){
        ed[++ednum].to=to;
        ed[ednum].dis=dis;
        ed[ednum].nxt=head[from];
        head[from]=ednum;
    }
    int dis[N];
    bool vis[N];
    int inf=0x3f3f3f3f;
    int spfa(int s,int t){
        if(hole[s]==1)
            s=n+1;
        memset(dis,0x3f,sizeof dis);
        memset(vis,0,sizeof vis);
    	queue<int> q;
        dis[s]=0;
        vis[s]=1;
        q.push(s);
    	while(!q.empty()){
    		int u=q.front();
    		q.pop();
            for(int i=head[u];i;i=ed[i].nxt){
    			int v=ed[i].to;
                if(dis[v]>dis[u]+ed[i].dis){
                    dis[v]=dis[u]+ed[i].dis;
                    if(!vis[v]){
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
            vis[u]=0;
        }
        return min(dis[t+n],dis[t]);
    }
    int main(){
    	freopen("holes.in","r",stdin);
    	freopen("holes.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&hole[i]);
        for(int i=1;i<=n;i++)
            scanf("%d",&w[i]);
        for(int i=1;i<=n;i++)
            scanf("%d",&s[i]);
        for(int i=1;i<=m;i++){
    		int from,to,dis;
            scanf("%d%d%d",&from,&to,&dis);
            if(hole[from]==hole[to]){
                add(from,to+n,dis);
                add(from+n,to,dis);
            }
            else{
                int tmp=abs(w[from]-w[to]);
                add(from+n,to+n,dis+tmp);
                add(from,to,max(dis-tmp,0));
            }
        }
        for(int i=1;i<=n;i++){
            add(i,i+n,0);
            add(i+n,i,s[i]);
        }
        printf("%d
    ",spfa(1,n));
        return 0;
    }
    

    我的程序

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    
    using namespace std;
    
    int n, m;
    
    struct edge{
    	int from, to, next, k;
    }ed[7001];//30000+30000+5000+5000
    
    int first[1001], en;
    
    void add(int u, int v, int k){
    	 ed[++en].to = v;
    	 ed[en].from = u;
    	 ed[en].next = first[u];
    	 ed[en].k = k;
    	 first[u] = en;
    }
    bool inque[1001], dist[1001];
    
    int co[501], w[501], s[501];
    
    int spfa(int s){
    	if(co[s])	s+=n;
    	for(int i=1;i<=n*2;i++)	dist[i]=1001;
    //	memset(inque, 0, sizeof(inque));
    	dist[s]=0;
    	queue<int>q;
    	q.push(s);
    	while(q.size()){
    //		cout << "&";
    		int now=q.front();q.pop();
    		inque[now]=false;
    		for(int i=first[now];i;i=ed[i].next){
    			
    			int e=ed[i].to;
    			int d=dist[now]+ed[i].k;
    //			cout << e << " " << d << " " << dist[e] << endl;
    			if(dist[e] > d){
    //				cout << "*" << e << " " << dist[e] << endl;
    				dist[e]=d;
    				if(!inque[e])	inque[e]=true,q.push(e);
    			}
    		}
    	}
    }
    
    int u, v, k;
    int ans;
    int main()
    {
    	cin >> n >> m;
    	for(int i=1;i<=2*n;i++)	dist[i]=1010;
    	bool t;int delta;
    	for(int i=1;i<=n;i++){
    		cin >> co[i];
    	}
    	for(int i=1;i<=n;i++){
    		cin >> w[i];
    	}
    	for(int i=1;i<=n;i++){
    		cin >> s[i];
    	}
    	for(int i=1;i<=m;i++){
    		cin >> u >> v >> k;
    		delta = abs(w[u] - w[v]);
    		if(co[u]==co[v])
    			add(u, v, k),add(u + n, v + n, k);
    		else{
    			add(u, v + n,k + delta);//白->黑 
    			add(u + n, v,  max(0, k - delta));//黑->白 
    		}
    	}
    	//1~n存白洞,n+1~n+n存黑洞 
    	for(int i=1;i<=n;i++){
    		add(i+n,i,s[i]);//黑洞停留消耗燃料
    		add(i,i+n,0);//白洞停留不消耗燃料 
    	}
    	/*
    	cout << en << endl;
    	for (int i=1;i<=n*2;i++){
    		cout<<i <<endl;
    		for(int e=first[i];e;e=ed[e].next)	cout << "<" << ed[e].to << " " << ed[e].k << "   ";
    		cout<< endl;
    	}*/
    
    /*
    	for(int i=1;i<=en;i++){
    		cout << ed[i].from << "pay" << ed[i].k << "to" << ed[i].to <<endl;
    	}
    */	
    	spfa(1);
    /*	
    	for (int i=1;i<=n;i++){
    		cout << dist[i] << " ";
    	}cout << endl;
    	ans = min(dist[n], dist[n*2]);
    	
    	spfa(1+n);
    	
    	if(min(dist[n], dist[n*2]) < ans)
    	*/ans = min(dist[n], dist[n*2]);
    	cout << ans << endl;
    
    	
    	return 0;
    }
    
    /*
    4 5
    1 0 1 0
    10 10 100 10
    5 20 15 10
    1 2 30
    2 3 40
    1 3 20
    1 4 200
    3 4 200
    */
    
  • 相关阅读:
    ZOJ 3631 Watashi's BG(dp+dfs)
    hdu 1506 Largest Rectangle in a Histogram(单调栈)
    csu 1392 Number Trick (数论)
    ACM 奋斗的小蜗牛
    ACM 16进制的简单运算
    ACM 交换输出
    ACM Longest Repeated Sequence
    ACM Arithmetic Expression
    ACM 素数
    ACM 无线网络覆盖
  • 原文地址:https://www.cnblogs.com/ZhengkunJia/p/12877208.html
Copyright © 2020-2023  润新知