题目大意:To see a World in a Grain of Sand
And a Heaven in a Wild Flower,
Hold Infinity in the palm of your hand
And Eternity in an hour.
?? William Blake
听说lcy帮大家预定了新马泰7日游,Wiskey真是高兴的夜不能寐啊,他想着得快点把这消息告诉大家,虽然他手上有所有人的联系方式,但是一个一个联系过去实在太耗时间和电话费了。他知道其他人也有一些别人的联系方式,这样他可以通知其他人,再让其他人帮忙通知一下别人。你能帮Wiskey计算出至少要通知多少人,至少得花多少电话费就能让所有人都被通知到吗?
解题思路:求出所有的强连通分量,接着缩点,然后找出所有强连通之间的关系。
找出所有入度为零的强连通分量(这些是必须要找一个人通知的),并找出这些强连通分量中价值最小的点
#include
#include
#define max(a,b) ((a) > (b) ? (a) : (b)) #define min(a,b) ((a) < (b) ? (a) : (b)) #define N 1010 #define M 2010 struct Edge{ int to, from, next, id; }E[M]; int head[N], cost[N], pre[N], lowlink[N], sccno[N], stack[N], in[N], out[N], money[N]; int n, m, tot, scc_cnt, top, dfs_clock;; bool vis[N]; void AddEdge(int from, int to) { E[tot].from = from; E[tot].to = to; E[tot].next = head[from]; E[tot].id = tot; head[from] = tot++; } void init() { memset(head, -1, sizeof(head)); tot = 0; for (int i = 1; i <= n; i++) scanf(%d, &cost[i]); int u, v; for (int i = 0; i < m; i++) { scanf(%d%d, &u, &v); AddEdge(u, v); } } void dfs(int u) { pre[u] = lowlink[u] = ++dfs_clock; stack[++top] = u; for (int i = head[u]; i != -1; i = E[i].next) { int v = E[i].to; if (!pre[v]) { dfs(v); lowlink[u] = min(lowlink[u], lowlink[v]); } else if (!sccno[v]) { lowlink[u] = min(lowlink[u], pre[v]); } } int x; if (pre[u] == lowlink[u]) { scc_cnt++; while (1) { x = stack[top--]; sccno[x] = scc_cnt; if (x == u) break; } } } void solve() { memset(pre, 0, sizeof(pre)); memset(sccno, 0, sizeof(sccno)); dfs_clock = top = scc_cnt = 0; for (int i = 1; i <= n; i++) if (!pre[i]) dfs(i); for (int i = 1; i <= scc_cnt; i++) in[i] = 1; memset(money, 0x3f, sizeof(money)); for (int i = 1; i <= n; i++) money[sccno[i]] = min(money[sccno[i]], cost[i]); int u, v; for (int i = 0; i < tot; i++) { u = E[i].from, v = E[i].to; if (sccno[u] != sccno[v]) in[sccno[v]] = 0; } int ans_man = 0, ans_cost = 0; for (int i = 1; i <= scc_cnt; i++) if (in[i]) { ans_man++; ans_cost += money[i]; } printf(%d %d , ans_man, ans_cost); } int main() { int cas = 1; while (scanf(%d%d, &n, &m) != EOF) { init(); solve(); } return 0; }
?