QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#14892 | #3020. Rainbow Graph | gmyu | ML | 1ms | 3524kb | C++11 | 6.9kb | 2021-10-25 07:02:29 | 2022-05-17 01:12:05 |
Judging History
answer
/*
ID: USACO_template
LANG: C++
PROG: https://open.kattis.com/problems/rainbowgraph
*/
#include <iostream> //cin , cout
#include <fstream> //fin, fout
#include <stdio.h> // scanf , pringf
#include <cstdio>
#include <algorithm> // sort , stuff
#include <stack> // stacks
#include <queue> // queues
#include <map>
#include <string>
#include <string.h>
#include <set>
using namespace std;
typedef pair<int, int> pii;
typedef vector<int> vi; /// adjlist without weight
typedef vector<pii> vii; /// adjlist with weight
typedef vector<pair<int,pii>> vpip; /// edge with weight
typedef long long ll;
#define mp make_pair
#define ff first
#define ss second
#define pb push_back
#define sz(x) (int)(x).size()
const int MOD = 1e9+7; // 998244353;
const int MX = 2e5+5; //
const ll INF = 1e18; //
#define MAXV 107
#define MAXE 107
struct EDGE {
int u, v;
ll w;
int id;
bool in; // mark whether this edge is included or not
bool operator<(EDGE other) const { return w < other.w; }
};
bool debug;
/** this is a matroid intersection problem
* learn at https://usaco.guide/adv/matroid-isect?lang=cpp
* the example code for this problem is at http://www.cs.ucf.edu/~dmarino/progcontests/mysols/northamerica/nac/2018/g.java
*/
int N, E;
EDGE ge[MAXE];
vii adj[2][MAXV]; // for roy/biv = 0/1, record adj at each node
int roy=0, biv=1;
ll totW;
bool removed[MAXE]; // which edge is removed
vector<EDGE> matGraph; // matroid graph
ll FACTOR = (ll)500;
int src, des;
ll dist[MAXE];
int p[MAXE];
/// check whether the graph is connected
bool visited[MAXV];
void dfs(int p, int u) {
if(visited[u]) return;
visited[u] = true;
for(auto x : adj[p][u]) {
if(!ge[x.ss].in) continue;
int nxt = x.ff;
if(!visited[nxt]) dfs(p, nxt);
}
}
bool connected(int p){
for(int i=1; i<=N; i++) visited[i] = false;
dfs(p, 1);
for(int i=1; i<=N; i++)
if(!visited[i]) return false;
return true;
}
// getMatGraph
void getMatGraph(){
// Set up according to remove.
for (int i=1; i<=E; i++) ge[i].in = !removed[i];
matGraph.clear();
// if removing an edge still lead to connected graph, connect this edge to src and des in MatGraph
// Add in all edges for removing an edge from roy or biv.
for (int i=1; i<=E; i++) {
if (!ge[i].in) continue;
// For roy, going from source. If still connected after removing an edge, connect source to i and make weight negative
// For biv, to destination.
ge[i].in = false;
if (connected(roy)) {
matGraph.pb({src, i, -FACTOR*ge[i].w + 1LL, -1, true});
if(debug) cout << " .. matGraph " << i << "th edge can be removed for roy " << -FACTOR*ge[i].w + 1LL << endl;
}
if (connected(biv)) {
matGraph.pb({i, des, 0LL + 1LL, -1, true});
if(debug) cout << " .. matGraph " << i << "th edge can be removed for biv 1" << endl;
}
ge[i].in = true;
}
// Sort out items in and out of our set.
vi rSet, bSet;
rSet.clear(); bSet.clear();
for (int i=1; i<=E; i++) {
if (!removed[i]) rSet.pb(i);
else bSet.pb(i);
}
// Add forward edges for removing something from rSet and adding back in something from bSet in roy's graph.
for (auto x: rSet) {
for (auto y: bSet) {
// if we can remove a non-removed edge and add a removed edge, we can connect the graph
// then we connect those two edges together
ge[x].in = false; ge[y].in = true;
if (connected(biv)) matGraph.pb({x, y, FACTOR*ge[y].w +1LL, -1, true}); // x -> y
if (connected(roy)) matGraph.pb({y, x, -FACTOR*ge[x].w +1LL, -1, true}); // y -> x
ge[x].in = true; ge[y].in = false;
}
}
/// now we form the matGraph, which as src for roy and des for biv (2 colors)
/// if we remove a edge and the original graph is still connected, then it is connected from src to des (the problem condition is met)
/// or if remove a non-removed edge and add a removed edge, we can connect the original graph, we link those 2 edge together, since those form the possible path from src to des as well
/// this matGraph represents how we can exclude edge and still make the problem work
}
int main() {
debug = false;
ios_base::sync_with_stdio(false); cin.tie(0);
cin >> N >> E;
for(int i=1;i<=E;i++) {
cin >> ge[i].u >> ge[i].v >> ge[i].w;
ge[i].id = i; ge[i].in = true; removed[i] = false;
totW += ge[i].w;
int a = ge[i].u, b = ge[i].v;
string str; cin >> str;
if(str == "R" || str == "G") { // Roy
adj[roy][a].pb(mp(b,i));
if(a!=b) adj[roy][b].pb(mp(a,i));
}
if(str == "B" || str == "G") {
adj[biv][a].pb(mp(b,i));
if(a!=b) adj[biv][b].pb(mp(a,i));
}
}
// if no connectivity
if(!connected(roy) || !connected(biv)) {
for(int i=1; i<=E; i++) cout << -1 << endl;
exit(0);
}
ll ans[MAXE];
for(int i=0;i<=E;i++) ans[i] = -1LL;
int idx = E;
ans[E] = totW;
idx--;
// do matroid intersection one by one
while(true && idx>0) {
if(debug) cout << "work on " << idx << " edges" << endl;
// Get the matroid graph - source is #e+1, dest is #(e+2)
src = E+1; des = E+2;
getMatGraph();
// Bellman-Ford on matroid graph
for(int i=0; i<=des; i++) {
dist[i] = INF; p[i] = -1;
}
dist[src] = 0LL;
for (int i=1; i<=des; i++) {
for (auto item: matGraph) {
if (dist[item.u] + item.w < dist[item.v]) {
dist[item.v] = dist[item.u] + item.w;
p[item.v] = item.u;
}
}
}
// Augmented our solution.
if (dist[des] < INF) {
// Build back path.
vi path; path.clear();
int cur = p[des];
while (cur != src) {
if(debug) cout << cur << " ";
path.pb(cur); cur = p[cur];
}
if(debug) cout << " edges removed" << endl;
// Flip all of these edges.
for (int x: path) removed[x] = !removed[x];
// Update solution for this many edges.
ans[idx] = 0LL;
for (int i=1; i<=E; i++)
if (!removed[i]) ans[idx] += ge[i].w;
// For next iteration.
idx--;
} else {
break;
}
}
for(int i=1; i<=E; i++) cout << ans[i] << endl;
if(debug) cout << endl << "EOL" << endl;
}
/*
5 8
1 5 1 R
2 1 2 R
5 4 5 R
4 5 3 G
1 3 3 G
4 3 5 G
5 4 1 B
1 2 2 B
*/
詳細信息
Test #1:
score: 100
Accepted
time: 1ms
memory: 3524kb
input:
5 8 1 5 1 R 2 1 2 R 5 4 5 R 4 5 3 G 1 3 3 G 4 3 5 G 5 4 1 B 1 2 2 B
output:
-1 -1 -1 -1 15 14 17 22
result:
ok 8 numbers
Test #2:
score: -100
Memory Limit Exceeded
input:
31 93 11 28 508 B 5 29 329 R 26 27 213 R 23 21 11 B 19 20 373 R 7 14 19 B 11 15 478 B 9 27 737 R 8 30 548 B 14 8 468 R 27 14 989 G 25 25 235 B 18 3 669 R 26 5 254 B 8 6 866 G 26 30 612 R 29 4 658 R 3 11 690 R 29 24 650 R 17 24 986 B 13 19 608 B 10 26 380 B 3 17 998 R 12 16 849 B 23 5 449 B 19 13 302...