A.患者的编号

给出一个有向图,要求你输出字典序最小的拓扑排序。

常规拓扑排序是做不了的,正解是反向建图,同时用大根堆的优先队列维护,保证每次优先访问编号大的结点,再反向输出~

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+14;
vector<int> g[maxn];
vector<int> topOrder;
int inDegree[maxn];
int N,M,x,y;
void topSort () {
    priority_queue<int> q;
    for (int i=1;i<=N;i++)
    if (inDegree[i]==0) q.push(i);
    while (!q.empty()) {
        int u=q.top();
        q.pop();
        topOrder.push_back(u);
        for (int i=0;i<g[u].size();i++) {
               int v=g[u][i];
               if (--inDegree[v]==0)
               q.push(v);
        }
    }
}
int num[maxn];
int main () {
    while(~scanf("%d %d",&N,&M)) {
        fill(inDegree,inDegree+maxn,0);
        topOrder.clear();
        for (int i=0;i<maxn;i++) g[i].clear();
        for (int i=0;i<M;i++) {
            scanf("%d %d",&x,&y);
            g[y].push_back(x);
            inDegree[x]++;
        }
        topSort();
        for (int i=0;i<topOrder.size();i++) {
            num[topOrder[i]]=N-i;
        }
        for (int i=1;i<=N;i++) {
            if (i!=1) printf (" ");
            printf ("%d",num[i]); 
        }
        printf ("\n");
    }
    return 0;
}

D.传送门

特殊的,点的权值也可以作为最小生成树的边,建树时贪心操作即可~

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2014;
const ll inf=1e18;
ll g[maxn][maxn];
ll w[maxn];
int visit[maxn];
ll d[maxn];
ll c[maxn];
int N;
ll prim (int s) {
    fill (d,d+maxn,inf);
    fill (visit,visit+maxn,0);
    d[s]=w[s];
    ll ans=0;
    for (int i=1;i<=N;i++) {
        int u=-1;ll mmin=inf;
        for (int j=1;j<=N;j++)
        if (!visit[j]&&d[j]<mmin) {
            u=j;
            mmin=d[j];
        }
        if (u==-1) return -1;
        visit[u]=1;
        ans+=d[u];
        //printf ("%d\n",d[u]);
        for (int v=1;v<=N;v++) 
        if (!visit[v]&&v!=u) d[v]=min(w[v],min(d[v],g[u][v]));
    }
    return ans;
}
struct node {
    int x,y;
}Node[maxn];
int main () {
    scanf("%d",&N);
    for (int i=1;i<=N;i++)
    for (int j=1;j<=N;j++) g[i][j]=inf;
    for (int i=1;i<=N;i++) scanf("%d %d",&Node[i].x,&Node[i].y);
    for (int i=1;i<=N;i++) scanf("%lld",&w[i]);
    for (int i=1;i<=N;i++) scanf("%lld",&c[i]);
    for (int i=1;i<=N;i++) {
        for (int j=i+1;j<=N;j++) {
            ll dis=(c[i]+c[j])*(abs(Node[i].x-Node[j].x)+abs(Node[i].y-Node[j].y));
            //printf ("%lld\n",dis);
            g[i][j]=g[j][i]=dis;
        }
    }
    int u=-1;
    ll mmin=inf;
    for (int i=1;i<=N;i++) {
        if (w[i]<mmin) {
            mmin=w[i];u=i;
        }
    } 
    ll ans=prim(u);
    printf ("%lld\n",ans);
    return 0;
}