• Luogu P1342 请柬 题解


    差不多是Dijkstra的裸题吧。。。

    • 这道题可以分为来回两个阶段。
    • 去的时候很简单,直接用一次Dijkstra,然后统计答案。
    • 回来的时候就有些巧妙了,虽然表面上是每个点回到起点,但是何尝不可将其看成从起点出发,逆着每个点过来的路去找一次每个点?所以只需要存边的时候处理一下,然后直接跑Dijkstra就行了。
    • 附上代码。
    #include<bits/stdc++.h>
    #define clean(a,i) memset(a,i,sizeof(a))
    #define ll long long
    #define inl inline
    #define il inl void
    #define it inl int
    #define ill inl ll
    #define re register
    #define ri re int
    #define rl re ll
    using namespace std;
    template<class T>il read(T &x)
    {
    	int f=1;char k=getchar();x=0;
    	for(;k>'9'||k<'0';k=getchar()) if(k=='-') f=-1;
    	for(;k>='0'&&k<='9';k=getchar()) x=(x<<3)+(x<<1)+k-'0';
    	x*=f;
    }
    const int MAXN = 1e6+5;
    int n,m,u,v,d,head[MAXN],num_edge,dis[MAXN];
    ll ans;
    struct Edge{
    	int next,to,dis,type; //存边的时候用了一个type标记,1表示它为正向边,2表示它为反向边
    	Edge(){}
    	Edge(int next,int to,int dis,int type):next(next),to(to),dis(dis),type(type){}
    }edge[MAXN<<1];
    il add_edge(int u,int v,int dis){
    	edge[++num_edge]=Edge(head[u],v,dis,1);head[u]=num_edge; //加正边
    	edge[++num_edge]=Edge(head[v],u,dis,2);head[v]=num_edge; //加反边
    }
    struct Node{
    	int pos,dis;
    	Node(){}
    	Node(int pos,int dis):pos(pos),dis(dis){}
    	bool operator <(const Node &t) const{
    		return dis>t.dis;
    	}
    };
    bool tr[MAXN];
    il dijkstra(int type){
    	priority_queue<Node> q;q.push(Node(1,0));
    	for(ri i=2;i<=n;i++) dis[i]=2147483647;
    	clean(tr,0);
    	while(!q.empty()){
    		Node tmp=q.top();q.pop();
    		ri pos=tmp.pos;
    		if(tr[pos]) continue;
    		tr[pos]=true;
    		for(ri i=head[pos];i;i=edge[i].next){
    			if(edge[i].type!=type) continue; //进行判断
    			if(dis[edge[i].to]>dis[pos]+edge[i].dis){
    				dis[edge[i].to]=dis[pos]+edge[i].dis;
    				if(!tr[edge[i].to]) q.push(Node(edge[i].to,dis[edge[i].to]));
    			}
    		}
    	}
    	for(ri i=2;i<=n;i++) ans+=dis[i]; //统计答案
    }
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	read(n),read(m);
    	for(ri i=1;i<=m;i++) read(u),read(v),read(d),add_edge(u,v,d);
    	dijkstra(1);dijkstra(2);
    	printf("%lld",ans); //答案记得开long long
    	return 0;
    }
    
    • 这道题其实更优的方法是开两个结构体,分别来存正反边,这样时间复杂度会小一些(毕竟不用每条边正反两个每次都要跑),但是为什么我没有这样写呢?当然是我懒啊
    • OK,完工。[]( ̄▽ ̄)*
  • 相关阅读:
    ruby学习总结03
    ruby学习总结02
    ruby学习总结01
    mongodb学习笔记
    mongodb数据库设计原则
    activiti学习总结
    Scala学习——隐式转换
    Scala学习——函数高级操作
    Scala学习——模式匹配
    Scala学习——集合
  • 原文地址:https://www.cnblogs.com/TheShadow/p/10660171.html
Copyright © 2020-2023  润新知