SDOI 2017 天才黑客
这题为了不写线段树优化连边写单log的前缀后缀连边调死我了。。。。。
码力榨干,题解咕咕咕
#include "iostream"
#include "algorithm"
#include "cstring"
#include "cstdio"
#include "vector"
#include "queue"
using namespace std;
#define mem(a) memset( a , 0 , sizeof a)
#define MAXN 1000006
#define pii pair<int,int>
#define pli pair<long long,int>
#define se second
#define fi first
#define mp make_pair
int n , m , k;
vector<pii> adj[MAXN];
int pos[MAXN];
int head[MAXN] , to[MAXN] , nex[MAXN] , wto[MAXN] , ecn;
void ade( int u , int v , int w ) {
// printf("%d %d %d\n",u,v,w);
to[++ ecn] = v , nex[ecn] = head[u] , head[u] = ecn , wto[ecn] = w;
}
vector<int> G[MAXN];
int cnt;
int dfn[MAXN] , cl , dep[MAXN] , g[MAXN][18];
void dfs( int u , int fa ) {
dfn[u] = ++ cl;
for( int i = 0 ; i < G[u].size() ; ++ i ) {
int v = G[u][i];
if( v == fa ) continue;
dep[v] = dep[u] + 1;
g[v][0] = u;
for( int k = 1 ; k < 18 ; ++ k )
if( g[g[v][k-1]][k-1] ) g[v][k] = g[g[v][k-1]][k-1];
else break;
dfs( v , u );
}
}
int lca( int u , int v ) {
if( dep[u] < dep[v] ) swap( u , v );
for( int k = 17 ; k >= 0 ; -- k ) if( dep[g[u][k]] >= dep[v] ) u = g[u][k];
if( u == v ) return dep[u];
for( int k = 17 ; k >= 0 ; -- k ) if( g[u][k] != g[v][k] ) u = g[u][k] , v = g[v][k];
return dep[g[u][0]];
}
bool cmp( pii a , pii b ) {
return dfn[pos[a.fi]] < dfn[pos[b.fi]];
}
int bac[MAXN];
priority_queue<pli> Q;
long long dis[MAXN]; int vis[MAXN];
void dijk( int s ) {
memset( dis , 0x3f3f , sizeof dis );
memset( vis , 0 , sizeof vis );
while( !Q.empty( ) ) Q.pop();
dis[s] = 0 , Q.push( mp( 0 , s ) );
while( !Q.empty() ) {
int u = Q.top().se; Q.pop();
if( vis[u] ) continue;
vis[u] = 1;
for( int i = head[u] ; i ; i = nex[i] ) {
int v = to[i];
if( dis[v] > dis[u] + wto[i] && !vis[v] )
dis[v] = dis[u] + wto[i] , Q.push( mp( -dis[v] , v ) );
}
}
}
long long ans[MAXN];
int main() {
// freopen("q.in","r",stdin);
int T;cin >> T;
while( T-- ) {
mem(head),mem(g),mem(dfn),mem(bac);
cnt = cl = ecn = 0;
cin >> n >> m >> k;
for( int i = 1 ; i <= n ; ++ i ) adj[i].clear();
for( int i = 1 ; i <= k ; ++ i ) G[i].clear();
cnt = ( m << 1 ) + 2;
for( int i = 1 , a , b , c , d ; i <= m ; ++ i ) {
scanf("%d%d%d%d", &a, &b, &c, &d);
adj[a].push_back(mp(i, 0)), adj[b].push_back(mp(i, 1)); // 0 : in , 1 : out
pos[i] = d;
ade(i << 1, i << 1 | 1, c);
if( a == 1 ) ade( cnt , i << 1 , 0 );
bac[i] = b;
}
for( int i = 1 , u , v ; i < k ; ++ i )
scanf("%d%d%*d",&u,&v) , G[u].push_back( v );
dfs( 1 , 1 );
for( int i = 1 ; i <= n ; ++ i ) {
sort( adj[i].begin() , adj[i].end() , cmp );
int sz = adj[i].size();
if( sz <= 1 ) continue;
vector<int> w; w.push_back( 0 );
for( int j = 1 ; j < sz ; ++ j )
w.push_back( lca( pos[adj[i][j - 1].fi] , pos[adj[i][j].fi] ) );
int prein , preout;
if( adj[i][0].se ) {
ade( adj[i][0].fi << 1 | 1 , ++ cnt , 0 ) , preout = cnt;
prein = ++ cnt;
} else {
ade( ++ cnt , adj[i][0].fi << 1 , 0 ) , prein = cnt;
preout = ++ cnt;
}
for( int j = 1 ; j < sz ; ++ j ) {
if( adj[i][j].se ) {
ade( adj[i][j].fi << 1 | 1 , ++ cnt , 0 ) , ade( preout , cnt , 0 );
ade( preout , cnt + 1 , w[j] ) , preout = cnt;
ade( prein , ++ cnt , 0 ) , prein = cnt;
} else {
ade( ++ cnt , adj[i][j].fi << 1 , 0 ) , ade( prein , cnt , 0 );
ade( preout , cnt , w[j] ) , prein = cnt;
ade( preout , ++ cnt , 0 ) , preout = cnt;
}
}
// reversed ...
if( adj[i][sz - 1].se ) {
ade( adj[i][sz - 1].fi << 1 | 1 , ++ cnt , 0 ) , preout = cnt;
prein = ++ cnt;
} else {
ade( ++ cnt , adj[i][sz - 1].fi << 1 , 0 ) , prein = cnt;
preout = ++ cnt;
}
for( int j = sz - 2 ; j >= 0 ; -- j ) {
if( adj[i][j].se ) {
ade( adj[i][j].fi << 1 | 1 , ++ cnt , 0 ) , ade( preout , cnt , 0 );
ade( preout , cnt + 1 , w[j + 1] ) , preout = cnt;
ade( prein , ++ cnt , 0 ) , prein = cnt;
} else {
ade( ++ cnt , adj[i][j].fi << 1 , 0 ) , ade( prein , cnt , 0 );
ade( preout , cnt , w[j + 1] ) , prein = cnt;
ade( preout , ++ cnt , 0 ) , preout = cnt;
}
}
}
dijk( ( m << 1 ) + 2 );
memset( ans , 0x3f3f , sizeof ans );
for( int i = 1 ; i <= m ; ++ i )
ans[bac[i]] = min( ans[bac[i]] , dis[i << 1 | 1] );
for( int i = 2 ; i <= n ; ++ i ) printf("%lld\n",ans[i]);
// puts("");
}
}