1. 程式人生 > >[SCOI2010]連續攻擊遊戲

[SCOI2010]連續攻擊遊戲

edge set rap long long 傳送門 min register getc def

題目傳送門

這道題是一個二分圖匹配問題。如果第$i$件裝備的屬性值為$j$,將裝備$i$連邊到屬性值$j$(註意裝備結點$≠$屬性值結點)。

然後從$1$到$10000$跑二分圖匹配,判斷該點是否能被匹配。直到不能匹配為止。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define re register
 6 #define rep(i, a, b) for (re int i = a; i <= b; ++i)
 7 #define repd(i, a, b) for (re int i = a; i >= b; --i)
 8
#define maxx(a, b) a = max(a, b); 9 #define minn(a, b) a = min(a, b); 10 #define LL long long 11 #define inf (1 << 30) 12 13 inline int read() { 14 int w = 0, f = 1; char c = getchar(); 15 while (!isdigit(c)) f = c == - ? -1 : f, c = getchar(); 16 while (isdigit(c)) w = (w << 3
) + (w << 1) + (c ^ 0), c = getchar(); 17 return w * f; 18 } 19 20 const int maxn = 1e6 + 5, maxm = 1e4 + 5; 21 22 struct Edge { 23 int u, v, pre; 24 }; 25 26 struct Graph { 27 Edge edges[maxn << 1]; 28 int G[maxm], n, m; 29 void init() { 30 memset(G, 0
, sizeof(G)); 31 n = 10000; 32 m = 0; 33 } 34 void Add(int u, int v) { 35 edges[++m] = (Edge){u, v, G[u]}; 36 G[u] = m; 37 } 38 int vis[maxn], lk[maxn]; 39 bool dfs(int u, int t) { 40 if (vis[u] == t) return 0; 41 vis[u] = t; 42 for (int i = G[u]; i; i = edges[i].pre) { 43 int v = edges[i].v; 44 if (!lk[v] || dfs(lk[v], t)) { 45 lk[v] = u; 46 return true; 47 } 48 } 49 return false; 50 } 51 int hungarian() { 52 rep(i, 1, 10000) { 53 if (!dfs(i, i)) // 這是時間戳的一種優化,否則會TLE。 54 return i-1; 55 } 56 return 10000; 57 } 58 } G; 59 60 int N; 61 62 int main() { 63 N = read(); 64 G.init(); 65 rep(i, 1, N) { 66 int u = read(), v = read(); 67 G.Add(u, i); 68 G.Add(v, i); 69 } 70 printf("%d", G.hungarian()); 71 72 return 0; 73 }

[SCOI2010]連續攻擊遊戲