1. 程式人生 > >Luogu P1342 請柬 題解

Luogu P1342 請柬 題解

include 只需要 階段 直接 mes 。。 prior print turn

差不多是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,完工。[]~( ̄▽ ̄)~*

Luogu P1342 請柬 題解