• 2017.7.11 图论测试



      我先用费用流的方法去跑spfa,然后完美T掉6个点。

      就说正解吧,正解是跑两次spfa,然后就可以找出最短路覆盖的边(详细过程请看代码rebuild())。然后建图跑最大流

    Code

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <ctime>
      4 #include <cmath>
      5 #include <cctype>
      6 #include <cstring>
      7 #include <cstdlib>
      8 #include <fstream>
      9 #include <sstream>
     10 #include <algorithm>
     11 #include <map>
     12 #include <set>
     13 #include <stack>
     14 #include <queue>
     15 #include <vector>
     16 #include <stack>
     17 #ifndef WIN32
     18 #define Auto "%lld"
     19 #else
     20 #define Auto "%I64d"
     21 #endif
     22 using namespace std;
     23 typedef bool boolean;
     24 const signed int inf = (signed)((1u << 31) - 1);
     25 const double eps = 1e-6;
     26 const int binary_limit = 128;
     27 #define smin(a, b) a = min(a, b)
     28 #define smax(a, b) a = max(a, b)
     29 #define max3(a, b, c) max(a, max(b, c))
     30 #define min3(a, b, c) min(a, min(b, c))
     31 template<typename T>
     32 inline boolean readInteger(T& u){
     33     char x;
     34     int aFlag = 1;
     35     while(!isdigit((x = getchar())) && x != '-' && x != -1);
     36     if(x == -1) {
     37         ungetc(x, stdin);    
     38         return false;
     39     }
     40     if(x == '-'){
     41         x = getchar();
     42         aFlag = -1;
     43     }
     44     for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0');
     45     ungetc(x, stdin);
     46     u *= aFlag;
     47     return true;
     48 }
     49 
     50 typedef class Edge {
     51     public:
     52         int end;
     53         int next;
     54         int flow;
     55         int cap;
     56         int lvl;
     57         Edge(int end = 0, int next = -1, int flow = 0, int cap = 0, int lvl = 0):end(end), next(next), flow(flow), cap(cap), lvl(lvl) {    }
     58 }Edge;
     59 
     60 typedef class MapManager {
     61     public:
     62         int ce;
     63         vector<Edge> edge;
     64         int* h;
     65         
     66         MapManager():ce(0), h(NULL) {        }
     67         MapManager(int nodes):ce(0) {
     68             h = new int[(const int)(nodes + 1)];
     69             memset(h, -1, sizeof(int) * (nodes + 1));
     70         }
     71         
     72         inline void addEdge(int from, int end, int flow, int cap, int lvl) {
     73             edge.push_back(Edge(end, h[from], flow, cap, lvl));
     74             h[from] = ce++;
     75         }
     76         
     77         inline void addDoubleEdge(int from, int end, int cap, int lvl) {
     78             if(cap == 0)    return;
     79             addEdge(from, end, 0, cap, lvl);
     80             addEdge(end, from, cap, cap, lvl);
     81         }
     82         
     83         Edge& operator [] (int pos) {
     84             return edge[pos];
     85         }
     86 }MapManager;
     87 #define m_begin(g, i) (g).h[(i)]
     88 #define m_endpos -1
     89 
     90 #define LL long long
     91 
     92 int n, m;
     93 int s, t;
     94 MapManager g;
     95 
     96 inline void init() {
     97     readInteger(n);
     98     readInteger(m);
     99     g = MapManager(n + 1);
    100     s = 1, t = n;
    101     for(int i = 1, a, b, c; i <= m; i++) {
    102         readInteger(a);
    103         readInteger(b);
    104         readInteger(c);
    105         g.addDoubleEdge(a, b, 1, c);
    106     }
    107 }
    108 
    109 queue<int> que;
    110 boolean* vis;
    111 LL *f;
    112 LL *f1;
    113 inline void init_spfa() {
    114     vis = new boolean[t + 1];
    115     f = new LL[t + 1];
    116     f1 = new LL[t + 1];
    117 }
    118 
    119 inline void spfa(int s, int t, LL* &f2, boolean sign) {
    120     memset(vis, false, sizeof(boolean) * (n + 1));
    121     memset(f2, 0x7f, sizeof(long long) * (n + 1));
    122     f2[s] = 0;
    123     que.push(s);
    124     while(!que.empty()) {
    125         int e = que.front();
    126         que.pop();
    127         vis[e] = false;
    128         for(int i = m_begin(g, e); i != m_endpos; i = g[i].next) {
    129             int& eu = g[i].end;
    130             if(g[i].flow ^ sign)    continue;
    131             if(f2[eu] > f2[e] + g[i].lvl) {
    132                 f2[eu] = f2[e] + g[i].lvl;
    133                 if(!vis[eu] && eu != t) {
    134                     vis[eu] = true;
    135                     que.push(eu);
    136                 } 
    137             }
    138         }
    139     }
    140 }
    141 
    142 boolean* onpath;
    143 MapManager rg;
    144 inline void rebuild() {
    145     rg = MapManager(t);
    146     onpath = new boolean[(t + 1)];
    147     memset(onpath, false, sizeof(boolean) * (t + 1));
    148     for(int i = 1; i <= n; i++)
    149         if(f[i] + f1[i] == f[t])
    150             onpath[i] = true;
    151     for(int i = s; i <= t; i++) {
    152         if(!onpath[i])    continue;
    153         for(int j = m_begin(g, i); j != m_endpos; j = g[j].next) {
    154             int& e = g[j].end;
    155             if(onpath[e] && g[j].flow == 0 && f[i] + g[j].lvl == f[e])
    156                 rg.addDoubleEdge(i, e, 1, 0); //,printf("%d->%d
    ", i, e);
    157         }
    158     }
    159 }
    160 
    161 int *divs;
    162 inline boolean bfs() {
    163     memset(divs, -1, sizeof(int) * (t + 1));
    164     que.push(s);
    165     divs[s] = 0;
    166     while(!que.empty()) {
    167         int e = que.front();
    168         que.pop();
    169         for(int i = m_begin(rg, e); i != m_endpos; i = rg[i].next) {
    170             int& eu = rg[i].end;
    171             if(divs[eu] != -1 || rg[i].cap == rg[i].flow)    continue;
    172             divs[eu] = divs[e] + 1;
    173             que.push(eu);
    174         }
    175     }
    176     return divs[t] != -1;
    177 }
    178 
    179 int *cur;
    180 int blockedflow(int node, int minf) {
    181     if(node == t || minf == 0)    return minf;
    182     int f, flow = 0;
    183     for(int& i = cur[node]; i != m_endpos; i = rg[i].next) {
    184         int& e = rg[i].end;
    185         if(divs[e] == divs[node] + 1 && (f = blockedflow(e, min(minf, rg[i].cap - rg[i].flow))) > 0) {
    186             rg[i].flow += f;
    187             rg[i ^ 1].flow -= f;
    188             flow += f;
    189             minf -= f;
    190             if(minf == 0)    return flow;
    191         }
    192     }
    193     return flow;
    194 }
    195 
    196 inline int dinic() {
    197     divs = new int[(t + 1)];
    198     cur = new int[(t + 1)];
    199     int maxflow = 0;
    200     while(bfs()) {
    201         for(int i = s; i <= t; i++)
    202             cur[i] = m_begin(rg, i);
    203         maxflow += blockedflow(s, inf);
    204     }
    205     return maxflow;
    206 }
    207 
    208 inline void solve() {
    209     printf("%d", dinic());
    210 }
    211 
    212 int main() {
    213     freopen("change.in", "r", stdin);
    214     freopen("change.out", "w", stdout);
    215     init();
    216     init_spfa();
    217     spfa(s, t, f, false);
    218     spfa(t, s, f1, true);
    219     rebuild();
    220     solve();
    221     return 0;
    222 }


      二分答案,然后奇、偶数分开分别连源点和汇点,两者加起来是素数就加一条边。特殊处理1,只保留一个。

    Code

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <ctime>
      4 #include <cmath>
      5 #include <cctype>
      6 #include <cstring>
      7 #include <cstdlib>
      8 #include <fstream>
      9 #include <sstream>
     10 #include <algorithm>
     11 #include <map>
     12 #include <set>
     13 #include <stack>
     14 #include <queue>
     15 #include <vector>
     16 #include <stack>
     17 #ifndef WIN32
     18 #define Auto "%lld"
     19 #else
     20 #define Auto "%I64d"
     21 #endif
     22 using namespace std;
     23 typedef bool boolean;
     24 const signed int inf = (signed)((1u << 31) - 1);
     25 const double eps = 1e-6;
     26 const int binary_limit = 128;
     27 #define smin(a, b) a = min(a, b)
     28 #define smax(a, b) a = max(a, b)
     29 #define max3(a, b, c) max(a, max(b, c))
     30 #define min3(a, b, c) min(a, min(b, c))
     31 template<typename T>
     32 inline boolean readInteger(T& u){
     33     char x;
     34     int aFlag = 1;
     35     while(!isdigit((x = getchar())) && x != '-' && x != -1);
     36     if(x == -1) {
     37         ungetc(x, stdin);    
     38         return false;
     39     }
     40     if(x == '-'){
     41         x = getchar();
     42         aFlag = -1;
     43     }
     44     for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0');
     45     ungetc(x, stdin);
     46     u *= aFlag;
     47     return true;
     48 }
     49 
     50 typedef class Edge {
     51     public:
     52         int end;
     53         int next;
     54         int flow;
     55         int cap;
     56         int lvl;
     57         Edge(int end = 0, int next = -1, int flow = 0, int cap = 0, int lvl = 0):end(end), next(next), flow(flow), cap(cap), lvl(lvl) {    }
     58 }Edge;
     59 
     60 typedef class MapManager {
     61     public:
     62         int ce;
     63         vector<Edge> edge;
     64         int* h;
     65         
     66         MapManager():ce(0), h(NULL) {        }
     67         MapManager(int nodes):ce(0) {
     68             h = new int[(const int)(nodes + 1)];
     69             memset(h, -1, sizeof(int) * (nodes + 1));
     70         }
     71         
     72         inline void addEdge(int from, int end, int flow, int cap, int lvl) {
     73             edge.push_back(Edge(end, h[from], flow, cap, lvl));
     74             h[from] = ce++;
     75         }
     76         
     77         inline void addDoubleEdge(int from, int end, int cap, int lvl) {
     78             if(cap == 0)    return;
     79 //            printf("%d -> %d (with the capt %d)
    ", from, end, cap);
     80             addEdge(from, end, 0, cap, lvl);
     81             addEdge(end, from, cap, cap, lvl);
     82         }
     83         
     84         Edge& operator [] (int pos) {
     85             return edge[pos];
     86         }
     87         
     88         inline void clear() {
     89             edge.clear();
     90             delete[] h;
     91         }
     92 }MapManager;
     93 #define m_begin(g, i) (g).h[(i)]
     94 #define m_endpos -1
     95 
     96 int n, m;
     97 int s, t;
     98 int *fs, *ts, *ls;
     99 
    100 inline void init() {
    101     readInteger(n);
    102     readInteger(m);
    103     s = 0, t = n + 1;
    104     fs = new int[(n + 1)];
    105     ts = new int[(n + 1)];
    106     ls = new int[(n + 1)];
    107     int sum = 0;
    108     for(int i = 1; i <= n; i++) {
    109         readInteger(fs[i]);
    110         readInteger(ts[i]);
    111         readInteger(ls[i]);
    112         sum += fs[i];
    113     }
    114     if(sum < m) {
    115         puts("-1");
    116         exit(0);
    117     }
    118 }
    119 
    120 int num = 0;
    121 const int limit = 2e7;
    122 int prime[1270608];
    123 boolean *vis;
    124 inline void Euler() {
    125     vis = new boolean[limit + 1];
    126     memset(vis, false, sizeof(boolean) * (limit + 1));
    127     for(int i = 2; i <= limit; i++) {
    128         if(!vis[i])    prime[num++] = i;
    129         for(int j = 0; j < num; j++) {
    130             int x = i * 1LL * prime[j];
    131             if(x > limit)    break;
    132             vis[x] = true;
    133             if((i % prime[j]) == 0)    break;
    134         }
    135     }
    136 }
    137 
    138 inline void init_map(MapManager& g, int mid, int& sum) {
    139     g = MapManager(t);
    140     int maxonef = 0, maxid = -1;
    141     for(int i = 1; i <= n; i++)
    142         if(ls[i] <= mid && ts[i] == 1 && fs[i] > maxonef)
    143             maxonef = fs[i], maxid = i;
    144     for(int i = 1; i <= n; i++) {
    145         if(((ts[i] == 1 && i == maxid) || (ts[i] != 1 && (ts[i] & 1) == 1)) && ls[i] <= mid)
    146             g.addDoubleEdge(s, i, fs[i], ls[i]), sum += fs[i];
    147         else if((ts[i] & 1) == 0 && ls[i] <= mid)
    148             g.addDoubleEdge(i, t, fs[i], ls[i]), sum += fs[i];
    149     }
    150     for(int i = 1; i <= n; i++) {
    151         if(!(ts[i] & 1))    continue;
    152         for(int j = 1; j <= n; j++) {
    153             if(!vis[ts[i] + ts[j]]) {
    154                 g.addDoubleEdge(i, j, inf, 0);
    155             }
    156         }
    157     }
    158 }
    159 
    160 int* dep;
    161 queue<int> que;
    162 MapManager g;
    163 inline boolean bfs(int mid) {
    164     memset(dep, -1, sizeof(int) * (t + 1));
    165     dep[s] = 0;
    166     que.push(s);
    167     while(!que.empty()) {
    168         int e = que.front();
    169         que.pop();
    170         for(int i = m_begin(g, e); i != m_endpos; i = g[i].next) {
    171             int& eu = g[i].end;
    172             if(dep[eu] != -1)    continue;
    173             if(g[i].lvl > mid)    continue;
    174             if(g[i].cap == g[i].flow)    continue;
    175             dep[eu] = dep[e] + 1;
    176             que.push(eu);
    177         }
    178     }
    179     return dep[t] != -1;
    180 }
    181 
    182 int* cur;
    183 int blockedflow(int node, int minf, int mid) {
    184     if(node == t || minf == 0)    return minf;
    185 //    cout << node << endl;
    186     int f, flow = 0;
    187     for(int& i = cur[node]; i != m_endpos; i = g[i].next) {
    188         int& e = g[i].end;
    189         if(g[i].lvl <= mid && dep[e] == dep[node] + 1 && (f = blockedflow(e, min(minf, g[i].cap - g[i].flow), mid)) > 0) {
    190             g[i].flow += f;
    191             g[i ^ 1].flow -= f;
    192             flow += f;
    193             minf -= f;
    194             if(minf == 0)    return flow;
    195         }
    196     }
    197     return flow;
    198 }
    199 
    200 inline void init_dinic() {
    201     dep = new int[(t + 1)];
    202     cur = new int[(t + 1)];
    203 }
    204 
    205 int dinic(int mid) {
    206     int sum = 0, maxflow = 0;
    207     init_map(g, mid, sum);
    208     while(bfs(mid)) {
    209         for(int i = s; i <= t; i++)
    210             cur[i] = m_begin(g, i);
    211         maxflow += blockedflow(s, inf, mid);
    212     }
    213     g.clear();
    214 //    cout << maxflow << endl;
    215     return sum - maxflow;
    216 }
    217 
    218 inline void solve() {
    219     int l = 1, r = (1e9) + 1;
    220     while(l <= r) {
    221         int mid = (l + r) >> 1;
    222         if(dinic(mid) >= m)    r = mid - 1;
    223         else l = mid + 1;
    224     }
    225     if(r == (1e9) + 1)    puts("-1");
    226     else printf("%d
    ", r + 1);
    227 }
    228 
    229 int main() {
    230     freopen("card.in", "r", stdin);
    231     freopen("card.out", "w", stdout);
    232     Euler();
    233     init();
    234     init_dinic();
    235     solve();
    236     return 0;
    237 }


      先Tarjan弄一发,然后开始spfa,转移的时候判一下起点和终点是否在同一强连通分量内。

    Code

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <ctime>
      4 #include <cmath>
      5 #include <cctype>
      6 #include <cstring>
      7 #include <cstdlib>
      8 #include <fstream>
      9 #include <sstream>
     10 #include <algorithm>
     11 #include <map>
     12 #include <set>
     13 #include <stack>
     14 #include <queue>
     15 #include <vector>
     16 #include <stack>
     17 #ifndef WIN32
     18 #define Auto "%lld"
     19 #else
     20 #define Auto "%I64d"
     21 #endif
     22 using namespace std;
     23 typedef bool boolean;
     24 const signed int inf = (signed)((1u << 31) - 1);
     25 const signed long long llf = (signed long long)((1ull << 61) - 1);
     26 const double eps = 1e-6;
     27 const int binary_limit = 128;
     28 #define smin(a, b) a = min(a, b)
     29 #define smax(a, b) a = max(a, b)
     30 #define max3(a, b, c) max(a, max(b, c))
     31 #define min3(a, b, c) min(a, min(b, c))
     32 template<typename T>
     33 inline boolean readInteger(T& u){
     34     char x;
     35     int aFlag = 1;
     36     while(!isdigit((x = getchar())) && x != '-' && x != -1);
     37     if(x == -1) {
     38         ungetc(x, stdin);    
     39         return false;
     40     }
     41     if(x == '-'){
     42         x = getchar();
     43         aFlag = -1;
     44     }
     45     for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0');
     46     ungetc(x, stdin);
     47     u *= aFlag;
     48     return true;
     49 }
     50 
     51 ///map template starts
     52 typedef class Edge{
     53     public:
     54         int end;
     55         int next;
     56         int w;
     57         Edge(const int end = 0, const int next = 0, const int w = 0):end(end), next(next), w(w){}
     58 }Edge;
     59 
     60 typedef class MapManager{
     61     public:
     62         int ce;
     63         int *h;
     64         Edge *edge;
     65         MapManager(){}
     66         MapManager(int points, int limit):ce(0){
     67             h = new int[(const int)(points + 1)];
     68             edge = new Edge[(const int)(limit + 1)];
     69             memset(h, 0, sizeof(int) * (points + 1));
     70         }
     71         inline void addEdge(int from, int end, int w){
     72             edge[++ce] = Edge(end, h[from], w);
     73             h[from] = ce;
     74         }
     75         inline void addDoubleEdge(int from, int end, int w){
     76             addEdge(from, end, w);
     77             addEdge(end, from, w);
     78         }
     79         Edge& operator [] (int pos) {
     80             return edge[pos];
     81         }
     82 }MapManager;
     83 #define m_begin(g, i) (g).h[(i)]
     84 ///map template ends
     85 
     86 #define LL long long
     87 
     88 typedef class Data {
     89     public:
     90         LL mag;
     91         LL dis;
     92         
     93         Data(LL mag = llf, LL dis = llf):mag(mag), dis(dis) {        }
     94 
     95         boolean operator < (Data b) const {
     96             if(mag != b.mag)    return mag < b.mag;
     97             return dis < b.dis;
     98         }
     99         
    100         Data operator + (Data b) {
    101             return Data(mag + b.mag, dis + b.dis);
    102         }
    103 }Data;
    104 
    105 int n, m;
    106 MapManager g;
    107 MapManager rg;
    108 
    109 inline void init() {
    110     readInteger(n);
    111     readInteger(m);
    112     g = MapManager(n, m);
    113     rg = MapManager(n, m);
    114     for(int i = 1, a, b, c; i <= m; i++) {
    115         readInteger(a);
    116         readInteger(b);
    117         readInteger(c);
    118         g.addEdge(a, b, c);
    119         rg.addEdge(b, a, c);
    120     }
    121 }
    122 
    123 int cnt = 0, scc = 0;
    124 int* visitID;
    125 int* exitID;
    126 boolean* visited;
    127 boolean* instack;
    128 stack<int> s;
    129 int *belong;
    130 inline void init_tarjan() {
    131     int an = n + 1;
    132     visitID = new int[(an)];
    133     exitID = new int[(an)];
    134     visited = new boolean[(an)];
    135     instack = new boolean[(an)];
    136     belong = new int[(an)];
    137     memset(visited, false, sizeof(boolean) * an);
    138     memset(instack, false, sizeof(boolean) * an);
    139     memset(belong, 0, sizeof(int) * an);
    140 }
    141 
    142 void tarjan(int node) {
    143     visitID[node] = exitID[node] = cnt++;
    144     visited[node] = instack[node] = true;
    145     s.push(node);
    146     
    147     for(int i = m_begin(g, node); i; i = g[i].next) {
    148         int& e = g[i].end;
    149         if(!visited[e]) {
    150             tarjan(e);
    151             smin(exitID[node], exitID[e]);
    152         } else if(instack[e]) {
    153             smin(exitID[node], visitID[e]);
    154         }
    155     }
    156     
    157     if(visitID[node] == exitID[node]) {
    158         int now = -1;
    159         scc++;
    160         while(now != node) {
    161             now = s.top();
    162             s.pop();
    163             instack[now] = false;
    164             belong[now] = scc;
    165         }
    166     }
    167 }
    168 
    169 deque<int> que;
    170 Data *f;
    171 boolean *vis;
    172 inline void spfa(int s) {
    173     f = new Data[n + 1];
    174     vis = new boolean[n + 1];
    175     memset(vis, false, sizeof(boolean) * (n + 1));
    176     que.push_front(s);
    177     f[s] = Data(0, 0);
    178     while(!que.empty()) {
    179         int e = que.front();
    180         que.pop_front();
    181         vis[e] = false;
    182         for(int i = m_begin(rg, e); i; i = rg[i].next) {
    183             int& eu = rg[i].end;
    184             Data w((belong[e] == belong[eu]) ? (1) : (0), rg[i].w);
    185             if(f[e] + w < f[eu]) {
    186                 f[eu] = f[e] + w;
    187                 if(!vis[eu]) {
    188                     vis[eu] = true;
    189                     if(!que.empty() && f[eu] < f[que.front()])
    190                         que.push_front(eu);
    191                     else
    192                         que.push_back(eu);
    193                 }
    194             }
    195         }
    196     }
    197 }
    198 
    199 inline void solve() {
    200     for(int i = 2; i <= n; i++) {
    201         if(f[i].mag == llf)
    202             puts("-1");
    203         else 
    204             printf(Auto" "Auto"
    ", f[i].mag, f[i].dis);
    205     }
    206 }
    207 
    208 int main() {
    209     freopen("festival.in", "r", stdin);
    210     freopen("festival.out", "w", stdout);
    211     init();
    212     init_tarjan();
    213     for(int i = 1; i <= n; i++)
    214         if(!visited[i])
    215             tarjan(i);
    216     spfa(1);
    217     solve();
    218     return 0;
    219 }
  • 相关阅读:
    Android入门第六篇之ListView (一)
    STL 二分查找三兄弟(lower_bound(),upper_bound(),binary_search())
    fastjson 之常见的数据类型与json的相互转换
    Jetty:配置安全
    xml文件格式例如以下
    《编程珠玑》---笔记。浏览此文,一窥此书。
    【Github教程】史上最全github用法:github入门到精通
    SSL连接建立过程分析(1)
    ant 安装
    GMM的EM算法实现
  • 原文地址:https://www.cnblogs.com/yyf0309/p/7154423.html
Copyright © 2020-2023  润新知