1. 程式人生 > >Codeforces 545E Paths and Trees 題解

Codeforces 545E Paths and Trees 題解

文章目錄

題意

,
, 使 u
u . u , . 給一張邊帶權無向圖,讓你求一棵邊權和最小的生成樹,使得\newline 點u在樹上到每個點的距離等於u在原圖中到每個點的最短路.\newline 給出這張圖和u,輸出最小邊權和以及構成這棵生成樹的邊集.

題解

大膽貪心,把每一個點相連的最短路上的邊相加.
注意最短路演算法中進行的鬆弛操作.
我們對經過每一個點的最短路上的邊標記為 e i d v eid_v .
那麼在跑最短路的時候,如果 d i s [ v ] > d i s [ u ] + c o s t dis[v]>dis[u]+cost ,那麼 e i d [ v ] = i . i d eid[v]=i.id ,即這條邊的編號.
如果 d i s [ v ] = d i s [ u ] + c o s t dis[v]=dis[u]+cost ,我們就貪心選較短的邊.
這樣下去除了起始點 u u 的所有點 v v e i d eid 組成的集合即為答案.

#include<bits/stdc++.h> //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rel register ll
#define rec register char
#define gc getchar
//#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<23,stdin),p1==p2)?-1:*p1++)
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
char buf[1<<23],*p1=buf,*p2=buf;
inline int read(){
  int x=0,f=1;char c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return f?x:-x;
  }
template <typename mitsuha>
inline bool read(mitsuha &x){
  x=0;int f=1;char c=gc();
  for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
  if (!~c) return 0;
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return x=f?x:-x,1;
  }
template <typename mitsuha>
inline int write(mitsuha x){
  if (!x) return 0&pc(48);
  if (x<0) pc('-'),x=-x;
  int bit[20],i,p=0;
  for (;x;x/=10) bit[++p]=x%10;
  for (i=p;i;--i) pc(bit[i]+48);
  return 0;
  }
inline char fuhao(){
  char c=gc();
  for (;isspace(c);c=gc());
  return c;
  }
}using namespace chtholly;
using namespace std;
const int yuzu=3e5,inf=0x3f3f3f3f;
typedef int fuko[yuzu|10];
typedef ll rize[yuzu|10];
struct edge{int to,cost,id;}e[yuzu|10];
vector<edge> lj[yuzu|10];

vector<int> ans;
namespace {
rize dis; fuko eid,vis; 
void spfa(int s) {
  memset(dis,0x3f,sizeof dis);
  queue<int> q;
  dis[s]=0,q.push(s);
  for (;!q.empty();) {
    int u=q.front(); q.pop();
    vis[u]=0;
    for (edge i:lj[u]) {
      int v=i.to; ll c=i.cost;
      if (dis[u]+c==dis[v]&&e[eid[v]].cost>c){
        eid[v]=i.id;
        if (!vis[v]) q.push(v),vis[v]=1;
        }
      if (dis[v]>dis[u]+c) {
        dis[v]=dis[u]+c;
        eid[v]=i.id;
        if (!vis[v]) q.push(v),vis[v]=1;
        }
      }
    }
  }
}

int main() {
int i,n,m,u,v,c;
read(n),read(m);
for (i=1;i<=m;++i) {
  read(u),read(v),read(c);
  lj[u].push_back(edge{v,c,i});
  lj[v].push_back(edge{u,c,i});
  e[i]=edge{v,c,i};
  }
e->cost=inf;
spfa(read());
ll llx=0;
for (i=1;i<=n;++i) if (eid[i]) ans.push_back(eid[i]),llx+=e[eid[i]].cost;
cout<<llx<<endl;
for (auto p:ans) write(p),p32;
}

謝謝大家.