給定乙個
n 個點
m條邊的有向無環圖,問刪掉某個點後最長路最小變成多少。
data constraint n≤
7500,m
≤100000
因為是dag,先考慮構出圖的拓補序。 設f
i 表示第1層的點到
i 最長路為fi
,gi 表示最後一層的點到
i 最長路為gi
。 在原圖中,那麼我們一條邊(u
,v) 對答案的貢獻就是fu
+gv+
1 ,現在按照拓補序依次嘗試刪除結點。那麼當
u 已被嘗試刪除過,且
v還未被刪除是,一條邊(u
,v) 對答案的貢獻一定是fu
+gv+
1 。
所以每次嘗試刪除
x 之前就將fi
+gx+
1刪除,之後就將fx
+gi+
1 加入資料結構。
資料結構維護最大值即可。注意f,
g 本身也能算貢獻。
時間複雜度:o(
nlog
n)
#include
#include
#include
#include
#include
#include
using
namespace
std ;
#define n 75000 + 10
#define m 100000 + 10
multiset
< int > q ;
int node[2*m] , next[2*m] , head[n] , _head[n] , tot ;
int d[n] , r[n] , f[n] , g[n] ;
int n , m , ans1 , ans2 = 0x7fffffff ;
void link( int u , int v )
void revlink( int u , int v )
void bfs()
}d[0] = j ;
}int main()
for (int i = 1 ; i <= n ; i ++ ) if ( r[i] == 0 ) d[++d[0]] = i ;
bfs() ;
for (int i = d[0] ; i >= 1 ; i -- )
g[now] ++ ;
}for (int i = 1 ; i <= d[0] ; i ++ )
f[now] ++ ;
}for (int i = 1 ; i <= n ; i ++ ) q.insert( g[i] ) ;
for (int i = 1 ; i <= d[0] ; i ++ )
for (int p = head[now] ; p ; p = next[p] )
q.insert( f[now] + g[node[p]] + 1 ) ;
q.insert( f[now] ) ;
}printf( "%d %d\n" , ans1 , ans2 ) ;
return
0 ;}
以上. CTSC2016時空旅行
當時看這道題ac的人數比較多,就開了這道題。很容易發現是這是乙個有關凸包的題。然後不知道怎麼維護凸包,一直在想cdq,感覺複雜度不行,於是被這玩意難住了 幸好有親學長yyh造福人類的題解 十分詳細,而且相對容易看懂些,腦迴路跟我差不多。發現主要是我沒學線段樹標記永久化,所以去學了一下這個東西 大概就...
CTSC2016 時空旅行
鏈結 題解首先要發現答案要我們求這個式子 ans min bigl x i x 2 c i bigr 顯而易見的是這種時空嫁接的關係會形成一棵樹。但是我們並不能像 noi2014 購票那樣直接在樹上維護一條鏈的棧,因為每個點代表的既有可能是加入乙個點,又有可能是刪除乙個點。考慮每個點的存在時間都是一...
BZOJ 3434 Wc2014 時空穿梭
題意 n維座標中要找c個點使得c個點在一條線上且每一維的座標單調遞增且不能超過每一維限定的值m i n 11,2 c 20,m i 100000 include using namespace std const int n 100005,md 10007 int c n 19 g 21 n f 2...