hdu3072Intelligence System(缩图+贪心)

传送门

题意:给我们一个有向图,形成环的路线不需要收费,形成环的路线上的所有点不收费,

对于其余点,我们需找到一个生成树,花费最小

吐槽:这题把我人搞晕了,先是看题没看懂,没看到形成环的路线上的点不收费这条,然后就

使劲想也不可能做出来,看了题解还没一个正常的,全是抄一个人的,那个人还没注释,模板还跟我很不一样,

而且变量定义那些巨怪,就能不创新数组就不创,我不知道你在节约个啥,多搞点数组会死啊,

终于看懂他的模板然后才知道环上的点不收费,然后套上自己的模板又超时了...思来想去以为是dfs死循环了

又写了个tuopo版本的贪心,结果还是超时,最后的最后发现是hd数组没初始化,我.....

思路:就是把先缩点,把那些不需要付钱的点去掉,然后再贪心

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 50100;
typedef long long ll;
struct edge {
    int f, t, w,nxt;
}e[maxn << 1];
int hd[maxn], tot;
void add(int f, int t,int w) {
    e[++tot] = { f,t,w,hd[f]};
    hd[f] = tot;
}
int n, m;
int low[maxn], dfn[maxn], cnt;
int stk[maxn], sk, instk[maxn];
int col[maxn], colnum;
int du[maxn],cost[maxn], vis[maxn];
void init() {
    memset(hd, 0, sizeof(hd));
    memset(dfn, 0, sizeof(dfn));
    memset(vis, 0, sizeof(vis));
    memset(du, 0, sizeof(du));
    memset(col, 0, sizeof(col));
    cnt = sk = colnum = tot = 0;
}
void tarjan(int u) {
    low[u] = dfn[u] = ++cnt;
    stk[++sk] = u; instk[u] = 1;
    for (int i = hd[u]; i; i = e[i].nxt) {
        int v = e[i].t;
        if (!dfn[v]) {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if(instk[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if (low[u] == dfn[u]) {
        colnum++;
        while (1) {
            int v = stk[sk--];
            instk[v] = 0;
            col[v] = colnum;//标记属于那个连通分量
            if (v == u)break;
        }
    }
}
//void dfs(int u) {
//    if (vis[u])return;
//    vis[u] = 1;
//    for (int i = hd[u]; i; i = e[i].nxt) {
//        int v = e[i].t, w = e[i].w;
//        dfs(v);
//        if (w < cost[v])cost[v] = w;
//    }
//}
int tuopo() {//贪心
    queue<int>q;
    memset(cost, 0x3f, sizeof(cost));//初始化设置为一个很大的数
    for (int i = 1; i <= colnum; i++) {
        if (!du[i]) {
            cost[i] = 0;
            q.push(i);
        }
    }
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (int i = hd[u]; i; i = e[i].nxt) {
            int v = e[i].t, w = e[i].w;
            if (cost[v] > w)cost[v] = w;
            du[v]--;
            if (du[v] == 0) q.push(v);
        }
    }
    int ans = 0;
    for (int i = 1; i <= colnum; i++) {
        ans += cost[i];
    }
    return ans;
}
int main() {
    //freopen("test.txt", "r", stdin);
    while (~scanf("%d%d", &n, &m)) {
        init();
        for (int i = 1; i <= m;i++) {
            int a, b, w; scanf("%d%d%d", &a, &b, &w);
            add(a, b, w);
        }
        for (int i = 0; i < n; i++) {
            if (!dfn[i]) {
                tarjan(i);
            }
        }
        memset(hd, 0, sizeof(hd)); tot = 0;
        //可以将就之前的数组来存,会简化很多,之前的那些点都没用了
        for (int i = 1; i <= m; i++) {
            int u = e[i].f, v = e[i].t, w = e[i].w;
            if (col[u] != col[v]) {
                add(col[u], col[v], w);
                du[col[v]]++;//入读+1
            }
        }
        /*
        memset(cost,0x3f,sizeof(cost));
        for (int i = 1; i <= colnum; i++) {
            if (du[i] == 0) {
                cost[i] = 0;
                dfs(i);
            }
        }*/
        /*int ans = 0;
        for (int i = 1; i <= colnum; i++) {
            ans += cost[i];
        }*/
        printf("%d\n",tuopo());
    }
    return 0;
}

 

  

posted @ 2021-04-02 20:07  cono奇犽哒  阅读(38)  评论(0)    收藏  举报