Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /// Maximum Matching in General Graphs (Randomized Algorithm)
- #define MAX 1010
- bool adj[MAX][MAX];
- int n, ar[MAX][MAX];
- const int MOD = 1073750017;
- int expo(long long x, int n){
- long long res = 1;
- while (n){
- if (n & 1) res = (res * x) % MOD;
- x = (x * x) % MOD;
- n >>= 1;
- }
- return (res % MOD);
- }
- int rank(int n){ /// hash = 646599
- long long inv;
- int i, j, k, u, v, x, r = 0, T[MAX];
- for (j = 0; j < n; j++){
- for (k = r; k < n && !ar[k][j]; k++){}
- if (k == n) continue;
- inv = expo(ar[k][j], MOD - 2);
- for (i = 0; i < n; i++){
- x = ar[k][i];
- ar[k][i] = ar[r][i];
- ar[r][i] = (inv * x) % MOD;
- }
- for (u = r + 1; u < n; u++){
- if (ar[u][j]){
- for (v = j + 1; v < n; v++){
- if (ar[r][v]){
- ar[u][v] = ar[u][v] - (((long long)ar[r][v] * ar[u][j]) % MOD);
- if (ar[u][v] < 0) ar[u][v] += MOD;
- }
- }
- }
- }
- r++;
- }
- return r;
- }
- int tutte(int n){
- int i, j;
- srand(time(0));
- clr(ar);
- for (i = 0; i < n; i++){
- for (j = i + 1; j < n; j++){
- if (adj[i][j]){
- unsigned int x = (rand() << 15) ^ rand();
- x = (x % (MOD - 1)) + 1;
- ar[i][j] = x, ar[j][i] = MOD - x;
- }
- }
- }
- return (rank(n) >> 1);
- }
- int main(){
- int T = 0, t, m, i, j, a, b;
- scanf("%d", &t);
- while (t--){
- clr(adj);
- scanf("%d %d", &n, &m);
- while (m--){
- scanf("%d %d", &a, &b);
- a--, b--;
- adj[a][b] = adj[b][a] = true;
- }
- printf("Case %d: %d\n", ++T, tutte(n));
- }
- return 0;
- }
- /// Min-cost Max-flow using SPFA (Shortest Path Faster Algorithm)
- /// 0 Based indexed for directed weighted graphs (for undirected graphs, just add two directed edges)
- namespace mcmf{
- const int MAX = 1000010;
- const long long INF = 1LL << 60;
- long long cap[MAX], flow[MAX], cost[MAX], dis[MAX];
- int n, m, s, t, Q[10000010], adj[MAX], link[MAX], last[MAX], from[MAX], visited[MAX];
- void init(int nodes, int source, int sink){
- m = 0, n = nodes, s = source, t = sink;
- for (int i = 0; i <= n; i++) last[i] = -1;
- }
- void addEdge(int u, int v, long long c, long long w){
- adj[m] = v, cap[m] = c, flow[m] = 0, cost[m] = +w, link[m] = last[u], last[u] = m++;
- adj[m] = u, cap[m] = 0, flow[m] = 0, cost[m] = -w, link[m] = last[v], last[v] = m++;
- }
- bool spfa(){
- int i, j, x, f = 0, l = 0;
- for (i = 0; i <= n; i++) visited[i] = 0, dis[i] = INF;
- dis[s] = 0, Q[l++] = s;
- while (f < l){
- i = Q[f++];
- for (j = last[i]; j != -1; j = link[j]){
- if (flow[j] < cap[j]){
- x = adj[j];
- if (dis[x] > dis[i] + cost[j]){
- dis[x] = dis[i] + cost[j], from[x] = j;
- if (!visited[x]){
- visited[x] = 1;
- if (f && rand() & 7) Q[--f] = x;
- else Q[l++] = x;
- }
- }
- }
- }
- visited[i] = 0;
- }
- return (dis[t] != INF);
- }
- pair <long long, long long> solve(){
- int i, j;
- long long mincost = 0, maxflow = 0;
- while (spfa()){
- long long aug = INF;
- for (i = t, j = from[i]; i != s; i = adj[j ^ 1], j = from[i]){
- aug = min(aug, cap[j] - flow[j]);
- }
- for (i = t, j = from[i]; i != s; i = adj[j ^ 1], j = from[i]){
- flow[j] += aug, flow[j ^ 1] -= aug;
- }
- maxflow += aug, mincost += aug * dis[t];
- }
- return make_pair(mincost, maxflow);
- }
- }
- vector < pair<int,int> > G[205] ;
- int leaves[205] ;
- int isLeaf[205] ;
- int lvl[205] ;
- int cst[205] ;
- void dfs (int u , int p , int l) {
- lvl[u] = l ;
- if (G[u].size() == 1 and u != 1) {
- leaves[u] = 1;
- isLeaf[u] = 1;
- return ;
- }
- isLeaf[u] = leaves[u] = 0 ;
- for(int i = 0 ; i < G[u].size() ; i++) {
- int v = G[u][i].first ;
- if (v!=p) {
- dfs(v,u,l+1) ;
- leaves[u] += leaves[v] ;
- }
- }
- }
- int main(){
- int tc , caseno = 1 ;
- scanf("%d" , &tc) ;
- while (tc--) {
- int n ; scanf("%d" , &n) ;
- for (int i = 1 ; i <= n ; i++) {
- G[i].clear() ;
- }
- int maxw = 40 ;
- for (int i = 1 ; i < n ; i++) {
- int u , v, w ;
- scanf("%d %d %d", &u,&v,&w) ;
- cst[i] = w ; maxw = max(maxw,w) ;
- G[u].push_back(make_pair(v,i)) ;
- G[v].push_back(make_pair(u,i)) ;
- }
- dfs(1,-1,1) ;
- int source = 0 , nodes = n+1 , sink = 1 ;
- mcmf :: init(nodes , source , sink) ;
- for (int i = 1 ; i <= n ; i++) {
- if (isLeaf[i]) {
- mcmf :: addEdge(source,i,maxw,0) ;
- }
- for (int j = 0 ; j < G[i].size() ; j++) {
- int v = G[i][j].first , c = cst[G[i][j].second] ;
- int u = i ;
- if (lvl[u] > lvl[v]) {
- mcmf :: addEdge(u,v,leaves[u]*maxw-c,0) ;
- }
- }
- }
- int m ; scanf("%d" , &m) ;
- while (m--) {
- int u , v , cap , w ;
- scanf("%d %d %d %d" , &u , &v , &cap , &w) ;
- if (lvl[v] > lvl[u]) swap(u,v) ;
- mcmf :: addEdge(u,v,cap,w) ;
- }
- printf ("Case #%d: " , caseno++) ;
- pair<int,int> res = mcmf::solve() ;
- if (res.second != maxw*leaves[1]) {
- printf ("-1\n") ;
- }
- else {
- printf ("%d\n" , res.first) ;
- }
- }
- }
- /// Minimum path cover/Maximum independent set in DAG
- #define MAX 505
- namespace dag{
- bool ar[MAX][MAX]; /// For transitive closure and minimum path cover with not necessarily disjoint vertex
- vector <int> adj[MAX];
- bool visited[MAX], first_set[MAX], second_set[MAX];
- int n, L[MAX], R[MAX], D[MAX], Q[MAX], dis[MAX], parent[MAX];
- inline void init(int nodes){ /// Number of vertices in DAG
- n = nodes;
- for (int i = 0; i < MAX; i++) adj[i].clear();
- }
- inline void add_edge(int u, int v){ /// 0 based index, directed edge of DAG
- adj[u].push_back(v);
- }
- bool dfs(int i){
- int len = adj[i].size();
- for (int j = 0; j < len; j++){
- int x = adj[i][j];
- if (L[x] == -1 || (parent[L[x]] == i)){
- if (L[x] == -1 || dfs(L[x])){
- L[x] = i, R[i] = x;
- return true;
- }
- }
- }
- return false;
- }
- bool bfs(){
- clr(visited);
- int i, j, x, d, f = 0, l = 0;
- for (i = 0; i < n; i++){
- if (R[i] == -1){
- visited[i] = true;
- Q[l++] = i, dis[i] = 0;
- }
- }
- while (f < l){
- i = Q[f++];
- int len = adj[i].size();
- for (j = 0; j < len; j++){
- x = adj[i][j], d = L[x];
- if (d == -1) return true;
- else if (!visited[d]){
- Q[l++] = d;
- parent[d] = i, visited[d] = true, dis[d] = dis[i] + 1;
- }
- }
- }
- return false;
- }
- void get_path(int i){
- first_set[i] = true;
- int j, x, len = adj[i].size();
- for (j = 0; j < len; j++){
- x = adj[i][j];
- if (!second_set[x] && L[x] != -1){
- second_set[x] = true;
- get_path(L[x]);
- }
- }
- }
- void transitive_closure(){ /// Transitive closure in O(n * m)
- clr(ar);
- int i, j, k, l;
- for (i = 0; i < n; i++){
- l = adj[i].size();
- for (j = 0; j < l; j++){
- ar[i][adj[i][j]] = true;
- }
- adj[i].clear();
- }
- for (k = 0; k < n; k++){
- for (i = 0; i < n; i++){
- if (ar[i][k]){
- for (j = 0; j < n; j++){
- if (ar[k][j]) ar[i][j] = true;
- }
- }
- }
- }
- for (i = 0; i < n; i++){
- for (j = 0; j < n; j++){
- if (i != j && ar[i][j]){
- adj[i].push_back(j);
- }
- }
- }
- }
- int minimum_disjoint_path_cover(){ /// Minimum vertex disjoint path cover in DAG. Handle isolated vertices appropriately
- int i, res = 0;
- memset(L, -1, sizeof(L));
- memset(R, -1, sizeof(R));
- while (bfs()){
- for (i = 0; i < n; i++){
- if (R[i] == -1 && dfs(i)) res++;
- }
- }
- return n - res;
- }
- int minimum_path_cover(){ /// Minimum path cover in DAG. Handle isolated vertices appropriately
- transitive_closure();
- return minimum_disjoint_path_cover();
- }
- vector <int> minimum_vertex_cover(){ /// Minimum vertex cover of DAG, equal to maximum bipartite matching
- int i, res = 0;
- memset(L, -1, sizeof(L));
- memset(R, -1, sizeof(R));
- while (bfs()){
- for (i = 0; i < n; i++){
- if (R[i] == -1 && dfs(i)) res++;
- }
- }
- vector <int> v;
- clr(first_set), clr(second_set);
- for (i = 0; i < n; i++){
- if (R[i] == -1) get_path(i);
- }
- for (i = 0; i < n; i++){
- if (!first_set[i] || second_set[i]) v.push_back(i);
- }
- return v;
- }
- vector <int> maximum_independent_set(){ /// Maximum independent set of DAG, all vertices not in minimum vertex cover
- vector <int> v = minimum_vertex_cover();
- clr(visited);
- int i, len = v.size();
- for (i = 0; i < len; i++) visited[v[i]] = true;
- vector <int> res;
- for (i = 0; i < n; i++){
- if (!visited[i]) res.push_back(i);
- }
- return res;
- }
- }
- /// Johnson's algo
- /// Johnson's algorithm for all pair shortest paths in sparse graphs
- /// Complexity: O(N * M) + O(N * M * log(N))
- #define MAX 2525
- const long long INF = (1LL << 60) - 666;
- struct edge{
- int u, v;
- long long w;
- edge(){}
- edge(int u, int v, long long w) : u(u), v(v), w(w){}
- void print(){
- cout << "edge " << u << " " << v << " " << w << endl;
- }
- };
- bool bellman_ford(int n, int src, vector <struct edge> E, vector <long long>& dis){
- dis[src] = 0;
- for (int i = 0; i <= n; i++){
- int flag = 0;
- for (auto e: E){
- if ((dis[e.u] + e.w) < dis[e.v]){
- flag = 1;
- dis[e.v] = dis[e.u] + e.w;
- }
- }
- if (flag == 0) return true;
- }
- return false;
- }
- vector <long long> dijkstra(int n, int src, vector <struct edge> E, vector <long long> potential){
- set<pair<long long, int> > S;
- vector <long long> dis(n + 1, INF);
- vector <long long> temp(n + 1, INF);
- vector <pair<int, long long> > adj[n + 1];
- dis[src] = temp[src] = 0;
- S.insert(make_pair(temp[src], src));
- for (auto e: E){
- adj[e.u].push_back(make_pair(e.v, e.w));
- }
- while (!S.empty()){
- pair<long long, int> cur = *(S.begin());
- S.erase(cur);
- int u = cur.second;
- for (int i = 0; i < adj[u].size(); i++){
- int v = adj[u][i].first;
- long long w = adj[u][i].second;
- if ((temp[u] + w) < temp[v]){
- S.erase(make_pair(temp[v], v));
- temp[v] = temp[u] + w;
- dis[v] = dis[u] + w;
- S.insert(make_pair(temp[v], v));
- }
- }
- }
- return dis;
- }
- void johnson(int n, long long ar[MAX][MAX], vector <struct edge> E){
- vector <long long> potential(n + 1, INF);
- for (int i = 1; i <= n; i++) E.push_back(edge(0, i, 0));
- assert(bellman_ford(n, 0, E, potential));
- for (int i = 1; i <= n; i++) E.pop_back();
- for (int i = 1; i <= n; i++){
- vector <long long> dis = dijkstra(n, i, E, potential);
- for (int j = 1; j <= n; j++){
- ar[i][j] = dis[j];
- }
- }
- }
- long long ar[MAX][MAX];
- int main(){
- vector <struct edge> E;
- E.push_back(edge(1, 2, 2));
- E.push_back(edge(2, 3, -15));
- E.push_back(edge(1, 3, -10));
- int n = 3;
- johnson(n, ar, E);
- for (int i = 1; i <= n; i++){
- for (int j = 1; j <= n; j++){
- printf("%d %d = %lld\n", i, j, ar[i][j]);
- }
- }
- return 0;
- }
- /// Hungarian algo
- #define MAX 666
- #define MAXIMIZE +1
- #define MINIMIZE -1
- #define inf (~0U >> 1)
- namespace wm{ /// hash = 581023
- bool visited[MAX];
- int U[MAX], V[MAX], P[MAX], way[MAX], minv[MAX], match[MAX], ar[MAX][MAX];
- /// n = number of row and m = number of columns in 1 based, flag = MAXIMIZE or MINIMIZE
- /// match[i] contains the column to which row i is matched
- int hungarian(int n, int m, int mat[MAX][MAX], int flag){
- clr(U), clr(V), clr(P), clr(ar), clr(way);
- for (int i = 1; i <= n; i++){
- for (int j = 1; j <= m; j++){
- ar[i][j] = mat[i][j];
- if (flag == MAXIMIZE) ar[i][j] = -ar[i][j];
- }
- }
- if (n > m) m = n;
- int i, j, a, b, c, d, r, w;
- for (i = 1; i <= n; i++){
- P[0] = i, b = 0;
- for (j = 0; j <= m; j++) minv[j] = inf, visited[j] = false;
- do{
- visited[b] = true;
- a = P[b], d = 0, w = inf;
- for (j = 1; j <= m; j++){
- if (!visited[j]){
- r = ar[a][j] - U[a] - V[j];
- if (r < minv[j]) minv[j] = r, way[j] = b;
- if (minv[j] < w) w = minv[j], d = j;
- }
- }
- for (j = 0; j <= m; j++){
- if (visited[j]) U[P[j]] += w, V[j] -= w;
- else minv[j] -= w;
- }
- b = d;
- } while (P[b] != 0);
- do{
- d = way[b];
- P[b] = P[d], b = d;
- } while (b != 0);
- }
- for (j = 1; j <= m; j++) match[P[j]] = j;
- return (flag == MINIMIZE) ? -V[0] : V[0];
- }
- }
- /// Hopcroft karp in O(m * sqrt(n))
- #define MAX 100010
- namespace hc{ /// hash = 393558
- bool visited[MAX];
- vector <int> adj[MAX];
- int n, L[MAX], R[MAX], Q[MAX], len[MAX], dis[MAX], parent[MAX];
- inline void init(int nodes){ /// Number of vertices in the left set, or max(left_set, right_set)
- n = nodes, clr(len);
- for (int i = 0; i < MAX; i++) adj[i].clear();
- }
- inline void add_edge(int u, int v){ /// 0 based index
- len[u]++;
- adj[u].push_back(v);
- }
- bool dfs(int i){
- for (int j = 0; j < len[i]; j++){
- int x = adj[i][j];
- if (L[x] == -1 || (parent[L[x]] == i)){
- if (L[x] == -1 || dfs(L[x])){
- L[x] = i, R[i] = x;
- return true;
- }
- }
- }
- return false;
- }
- bool bfs(){
- clr(visited);
- int i, j, x, d, f = 0, l = 0;
- for (i = 0; i < n; i++){
- if (R[i] == -1){
- visited[i] = true;
- Q[l++] = i, dis[i] = 0;
- }
- }
- while (f < l){
- i = Q[f++];
- for (j = 0; j < len[i]; j++){
- x = adj[i][j], d = L[x];
- if (d == -1) return true;
- else if (!visited[d]){
- Q[l++] = d;
- parent[d] = i, visited[d] = true, dis[d] = dis[i] + 1;
- }
- }
- }
- return false;
- }
- int hopcroft_karp(){
- int res = 0;
- memset(L, -1, sizeof(L));
- memset(R, -1, sizeof(R));
- while (bfs()){
- for (int i = 0; i < n; i++){
- if (R[i] == -1 && dfs(i)) res++;
- }
- }
- return res;
- }
- }
- int main(){
- int n, m, r, i, j, a, b;
- scanf("%d %d %d", &n, &m, &r);
- hc::init(max(n, m));
- while (r--){
- scanf("%d %d", &a, &b);
- hc::add_edge(--a, --b);
- }
- printf("%d\n", hc::hopcroft_karp());
- return 0;
- }
- /// Dinic's algorithm for directed graphs (0 based index for graphs)
- /// For undirected graphs, just add two directed edges
- #define MAXN 50010
- const long long INF = (~0ULL) >> 1;
- namespace flow{
- struct Edge{
- int u, v;
- long long cap, flow;
- Edge(){}
- Edge(int a, int b, long long c, long long f){
- u = a, v = b, cap = c, flow = f;
- }
- };
- vector <int> adj[MAXN];
- vector <struct Edge> E;
- int n, s, t, ptr[MAXN], len[MAXN], dis[MAXN], Q[MAXN];
- inline void init(int nodes, int source, int sink){
- clr(len);
- E.clear();
- n = nodes, s = source, t = sink;
- for (int i = 0; i < MAXN; i++) adj[i].clear();
- }
- /// Adds a directed edge with capacity c
- inline void addEdge(int a, int b, long long c){
- adj[a].push_back(E.size());
- E.push_back(Edge(a, b, c, 0));
- len[a]++;
- adj[b].push_back(E.size());
- E.push_back(Edge(b, a, 0, 0));
- len[b]++;
- }
- inline bool bfs(){
- int i, j, k, id, f = 0, l = 0;
- memset(dis, -1, sizeof(dis[0]) * n);
- dis[s] = 0, Q[l++] = s;
- while (f < l && dis[t] == -1){
- i = Q[f++];
- for (k = 0; k < len[i]; k++){
- id = adj[i][k];
- if (dis[E[id].v] == -1 && E[id].flow < E[id].cap){
- Q[l++] = E[id].v;
- dis[E[id].v] = dis[i] + 1;
- }
- }
- }
- return (dis[t] != -1);
- }
- long long dfs(int i, long long f){
- if (i == t || !f) return f;
- while (ptr[i] < len[i]){
- int id = adj[i][ptr[i]];
- if (dis[E[id].v] == dis[i] + 1){
- long long x = dfs(E[id].v, min(f, E[id].cap - E[id].flow));
- if (x){
- E[id].flow += x, E[id ^ 1].flow -= x;
- return x;
- }
- }
- ptr[i]++;
- }
- return 0;
- }
- long long dinic(){
- long long res = 0;
- while (bfs()){
- memset(ptr, 0, n * sizeof(ptr[0]));
- while (long long f = dfs(s, INF)) {
- res += f;
- }
- }
- return res;
- }
- }
- namespace nodeflow{
- void init(int n, int s, int t, vector <long long> capacity){
- flow::init(n * 2, s * 2, t * 2 + 1);
- for (int i = 0; i < n; i++){
- flow::addEdge(i * 2, i * 2 + 1, capacity[i]);
- }
- }
- void addEdge(int a, int b, long long c){
- flow::addEdge(a * 2 + 1, b * 2, c);
- }
- long long dinic(){
- return flow::dinic();
- }
- }
- int main(){
- int n , b , q ;
- cin >> n >> b >> q ;
- vector < pair<int,int> > v ;
- v.push_back({b,n}) ;
- v.push_back({0,0}) ;
- for (int i = 1 ; i <= q ; i++) {
- int x , k ;
- cin >> x >> k ;
- v.push_back({x,k}) ;
- }
- sort(v.begin(), v.end()) ;
- v.erase(unique(v.begin(),v.end()),v.end()) ;
- int source = 0 , nodes = 1 + 5 + v.size() , sink = nodes-1 ;
- flow :: init(nodes,source,sink) ;
- for (int i = 1 ; i <= 5 ; i++) {
- flow :: addEdge(source,i,n/5) ;
- }
- for (int i = 1 ; i < v.size() ; i++) {
- int cnt = v[i].second - v[i-1].second ;
- if (cnt < 0) {
- printf ("unfair") ;
- return 0 ;
- }
- flow :: addEdge(i+5,sink,+cnt) ;
- int l = v[i-1].first+1 , r = v[i].first ;
- if (l > r) {
- printf ("unfair") ;
- return 0 ;
- }
- int count_[5] ;
- memset (count_ , 0 , sizeof count_) ;
- for (int x = l ; x <= r ; x++) {
- count_[x%5]++ ;
- }
- for (int j = 1 ; j <= 5 ; j++) {
- flow::addEdge(j,i+5,count_[j-1]) ;
- }
- }
- if (flow::dinic() == n) {
- printf ("fair") ;
- }
- else {
- printf ("unfair") ;
- }
- return 0;
- }
- /// Dinic's algorithm for directed graphs (0 based index for graphs)
- /// For undirected graphs, just add two directed edges
- #define MAXN 5010
- const long long INF = (~0ULL) >> 1;
- namespace flow{
- int n, s, t, ptr[MAXN], dis[MAXN], Q[MAXN];
- long long cap[MAXN][MAXN], flow[MAXN][MAXN];
- inline void init(int nodes, int source, int sink){
- clr(cap), clr(flow);
- n = nodes, s = source, t = sink;
- }
- inline void addEdge(int a, int b, int c){
- cap[a][b] += c;
- }
- inline bool bfs(){
- int i, j, f = 0, l = 0;
- memset(dis, -1, sizeof(dis[0]) * n);
- dis[s] = 0, Q[l++] = s;
- while (f < l){
- i = Q[f++];
- for (j = 0; j < n; j++){
- if (dis[j] == -1 && flow[i][j] < cap[i][j]){
- Q[l++] = j;
- dis[j] = dis[i] + 1;
- }
- }
- }
- return (dis[t] != -1);
- }
- long long dfs(int i, long long f){
- if (i == t || !f) return f;
- for (int &j = ptr[i]; j < n; j++){
- if (dis[j] == (dis[i] + 1)){
- long long x = dfs(j, min(f, cap[i][j] - flow[i][j]));
- if (x){
- flow[i][j] += x, flow[j][i] -= x;
- return x;
- }
- }
- }
- return 0;
- }
- long long dinic(){
- long long res = 0;
- while (bfs()){
- memset(ptr, 0, n * sizeof(ptr[0]));
- while (long long f = dfs(s, INF)){
- res += f;
- }
- }
- return res;
- }
- }
- int main(){
- int n, i, j, k, a, b, c, s, t, m;
- n = MAXN - 10;
- s = 0, t = n - 1;
- flow::init(n, s, t);
- m = n * 1.75;
- while (m--){
- a = ran(0, n - 1);
- b = ran(0, n - 1);
- c = ran(1, 1000000000);
- flow::addEdge(a, b, c);
- }
- clock_t start = clock();
- printf("%lld\n", flow::dinic());
- fprintf(stderr, "%0.6f\n", (clock() - start) / (1.0 * CLOCKS_PER_SEC));
- return 0;
- }
- /// Directed minimum spanning tree in O(n * m)
- /// Constructs a rooted tree of minimum total weight from the root node
- /// Returns -1 if no solution from root
- struct Edge{
- int u, v, w;
- Edge(){}
- Edge(int a, int b, int c){
- u = a, v = b, w = c;
- }
- };
- int directed_MST(int n, vector <Edge> E, int root){ /// hash = 547539
- const int INF = (1 << 30) - 30;
- int i, j, k, l, x, y, res = 0;
- vector <int> cost(n), parent(n), label(n), comp(n);
- for (; ;){
- for (i = 0; i < n; i++) cost[i] = INF;
- for (auto e: E){
- if (e.u != e.v && cost[e.v] > e.w){
- cost[e.v] = e.w;
- parent[e.v] = e.u;
- }
- }
- cost[root] = 0;
- for (i = 0; i < n && cost[i] != INF; i++){};
- if (i != n) return -1; /// No solution
- for (i = 0, k = 0; i < n; i++) res += cost[i];
- for (i = 0; i < n; i++) label[i] = comp[i] = -1;
- for (i = 0; i < n; i++){
- for (x = i; x != root && comp[x] == -1; x = parent[x]) comp[x] = i;
- if (x != root && comp[x] == i){
- for (k++; label[x] == -1; x = parent[x]) label[x] = k - 1;
- }
- }
- if (k == 0) break;
- for (i = 0; i < n; i++){
- if (label[i] == -1) label[i] = k++;
- }
- for (auto &e: E){
- x = label[e.u], y = label[e.v];
- if (x != y) e.w -= cost[e.v];
- e.u = x, e.v = y;
- }
- root = label[root], n = k;
- }
- return res;
- }
- int main(){
- int T = 0, t, n, m, i, j, k, u, v, w, res;
- scanf("%d", &t);
- while (t--){
- vector <Edge> E;
- scanf("%d %d", &n, &m);
- for (i = 0; i < m; i++){
- scanf("%d %d %d", &u, &v, &w);
- E.push_back(Edge(u, v, w));
- }
- res = directed_MST(n, E, 0);
- if (res == -1) printf("Case #%d: Possums!\n", ++T);
- else printf("Case #%d: %d\n", ++T, res);
- }
- return 0;
- }
- /// Bridge (Extended)
- #define MAX 100010
- /// Note: 0-based indexing for graphs
- struct bridge{
- int u, v, w; /// Bridge from node u to v with cost w
- int f, s; /// Number of components in the first and second graph if bridge is disconnected
- bridge(){
- }
- bridge(int a, int b, int c, int d, int e){
- if (a > b) swap(a, b); /// Lower node first for convenience
- u = a, v = b, w = c, f = d, s = e;
- }
- };
- namespace br{
- typedef pair<int, int> Pair;
- bool visited[MAX];
- vector <bridge> B;
- vector <Pair> adj[MAX];
- tr1::unordered_set <long long> S;
- int n, r, dt, discover[MAX], low[MAX], cmp[MAX], num[MAX];
- void init(int nodes){
- n = nodes;
- for (int i = 0; i < MAX; i++) adj[i].clear();
- }
- void dfs(int i, int p){ /// hash = 60375
- visited[i] = true;
- discover[i] = low[i] = ++dt;
- int j, x, l, children = 0, len = adj[i].size();
- for (j = 0; j < len; j++){
- x = adj[i][j].first;
- if (!visited[x]){
- dfs(x, i);
- children++;
- low[i] = min(low[i], low[x]);
- if (low[x] > discover[i]){
- if (!(j && adj[i][j - 1].first == x) || ( (j + 1) < len && adj[i][j + 1].first == x) ){ /// Handling multi-edge
- l = dt - discover[x] + 1;
- B.push_back( bridge(i, x, adj[i][j].second, l, cmp[i] - l) );
- }
- }
- }
- else if (x != p) low[i] = min(low[i], discover[x]);
- }
- }
- void dfs(int i){
- low[dt++] = i;
- visited[i] = true;
- int j, x, len = adj[i].size();
- for (j = 0; j < len; j++){
- x = adj[i][j].first;
- if (!visited[x]){
- dfs(x);
- }
- }
- }
- /// Adds undirected edge from a to b with cost c or edge index number i
- void add(int a, int b, int c){
- adj[a].push_back(Pair(b, c));
- adj[b].push_back(Pair(a, c));
- }
- void FindBridge(){
- int i, j;
- B.clear();
- memset(visited, 0, sizeof(visited));
- for (i = 0; i < n; i++) sort(adj[i].begin(), adj[i].end()); /// To handle multi-edges
- for (i = 0; i < n; i++){
- if (!visited[i]){
- dt = 0;
- dfs(i);
- for (j = 0; j < dt; j++) cmp[low[j]] = dt;
- }
- }
- memset(visited, 0, sizeof(visited));
- for (i = 0; i < n; i++){
- if (!visited[i]){
- dt = 0;
- dfs(i, -1);
- }
- }
- }
- long long hashval(long long u, long long v){
- return (u * MAX) + v;
- }
- void dfsnum(int i){
- num[i] = r;
- visited[i] = true;
- int j, x, len = adj[i].size();
- for (j = 0; j < len; j++){
- x = adj[i][j].first;
- if (!visited[x] && !S.count(hashval(i, x))){
- dfsnum(x);
- }
- }
- }
- /// Call FindBridge before
- void BridgeTree(){
- S.clear();
- int i, j, x, u, v, len = B.size();
- for (i = 0; i < len; i++){
- S.insert(hashval(B[i].u, B[i].v));
- S.insert(hashval(B[i].v, B[i].u));
- }
- r = 0; /// Number of nodes in bridge tree
- memset(visited, 0, sizeof(visited));
- for (i = 0; i < n; i++){
- if (!visited[i]){
- dfsnum(i);
- r++;
- }
- }
- for (i = 0; i < len; i++){
- u = B[i].u, v = B[i].v;
- /// Build the bridge tree here accordingly
- }
- }
- }
- /// bipartite matching
- #define MAX 1010
- bool visited[MAX];
- int t, line, n, m, ar[MAX][MAX], adj[MAX][MAX], left[MAX], right[MAX], len[MAX];
- bool bipartite_matching(int u){
- int v = 0, j = 0;
- for (j = 0; j < len[u]; j++){
- v = adj[u][j];
- if (visited[v]) continue;
- visited[v] = true;
- if (right[v] == -1 || bipartite_matching(right[v])){
- left[u] = v;
- right[v] = u;
- return true;
- }
- }
- return false;
- }
- int max_matching(){
- memset(left, -1, sizeof(left));
- memset(right, -1, sizeof(right));
- int i, counter = 0;
- for (i = 0; i < n; i++){
- memset(visited, 0, sizeof(visited));
- if (bipartite_matching(i)) counter++;
- }
- return counter;
- }
- int main(){
- int a, b;
- while (scanf("%d %d", &n, &m) != EOF){
- memset(len, 0, sizeof(len));
- while (m--){
- scanf("%d %d", &a, &b);
- adj[a][len[a]++] = b;
- }
- }
- return 0;
- }
- /// 2 SAT (1 based index for variables)
- /// Each variable can have two possible values (true or false)
- /// Variables must satisfy a system of constraints on pairs of variables
- #define MAX 100010
- namespace sat{
- bool visited[MAX * 2];
- vector <int> adj[MAX * 2], rev[MAX * 2];
- int n, m, l, dfs_t[MAX * 2], order[MAX * 2], parent[MAX * 2];
- inline int neg(int x){
- return ((x) <= n ? (x + n) : (x - n));
- }
- /// Call init once
- void init(int nodes){
- n = nodes, m = nodes * 2;
- for (int i = 0; i < MAX * 2; i++){
- adj[i].clear();
- rev[i].clear();
- }
- }
- /// Add implication, if a then b
- inline void add_implication(int a, int b){
- if (a < 0) a = n - a;
- if (b < 0) b = n - b;
- adj[a].push_back(b);
- rev[b].push_back(a);
- }
- inline void add_or(int a, int b){
- add_implication(-a, b);
- add_implication(-b, a);
- }
- inline void add_xor(int a, int b){
- add_or(a, b);
- add_or(-a, -b);
- }
- inline void add_and(int a, int b){
- add_or(a, b);
- add_or(a, -b);
- add_or(-a, b);
- }
- /// force variable x to be true (if x is negative, force !x to be true)
- inline void force_true(int x){
- if (x < 0) x = n - x;
- add_implication(neg(x), x);
- }
- /// force variable x to be false (if x is negative, force !x to be false)
- inline void force_false(int x){
- if (x < 0) x = n - x;
- add_implication(x, neg(x));
- }
- inline void topsort(int i){
- visited[i] = true;
- int j, x, len = rev[i].size();
- for (j = 0; j < len; j++){
- x = rev[i][j];
- if (!visited[x]) topsort(x);
- }
- dfs_t[i] = ++l;
- }
- inline void dfs(int i, int p){
- parent[i] = p;
- visited[i] = true;
- int j, x, len = adj[i].size();
- for (j = 0; j < len; j++){
- x = adj[i][j];
- if (!visited[x]) dfs(x, p);
- }
- }
- void build(){
- int i, x;
- memset(visited, 0, sizeof(visited));
- for (i = m, l = 0; i >= 1; i--){
- if (!visited[i]){
- topsort(i);
- }
- order[dfs_t[i]] = i;
- }
- memset(visited, 0, sizeof(visited));
- for (i = m; i >= 1; i--){
- x = order[i];
- if (!visited[x]){
- dfs(x, x);
- }
- }
- }
- /// Returns true if the system is 2-satisfiable and returns the solution (nodes set to true) in vector res
- bool satisfy(vector <int>& res){
- build();
- memset(visited, 0, sizeof(visited));
- for (int i = 1; i <= m; i++){
- int x = order[i];
- if (parent[x] == parent[neg(x)]) return false;
- if (!visited[parent[x]]){
- visited[parent[x]] = true;
- visited[parent[neg(x)]] = false;
- }
- }
- res.clear();
- for (int i = 1; i <= n; i++){
- if (visited[parent[i]]) res.push_back(i);
- }
- return true;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement