恰好属于一个圈,那等价与每个点有唯一的前驱和后继,这让人想到了二分图,
把一个点拆开,点的前驱作为S集和点的后继作为T集,然后连边,跑二分图最小权完美匹配。
写的费用流。。最大权完美匹配KM算法没看懂
#include<bits/stdc++.h>
using namespace std; const int maxn = +;
struct Edge
{
int v,cap,cost,nxt;
}; vector<Edge> edges;
#define PB push_back
int head[maxn]; void addEdge(int u,int v,int C,int c)
{
edges.PB(Edge{v,C,c,head[u]});
head[u] = edges.size()-;
} void AddEdge(int u,int v,int C,int c)
{
addEdge(u,v,C,c);
addEdge(v,u,,-c);
}
typedef int ll;
int S = ,T = ,vcnt;
int d[maxn],p[maxn],a[maxn];
bool vis[maxn];
const int INF = 0x3f3f3f3f; ll MCMF(ll &cost)
{
cost = ;
ll flow = ;
while(true){
memset(vis,,sizeof(bool)*vcnt);
memset(d,0x3f,sizeof(int)*vcnt);
queue<int> q;
q.push(S); d[S] = ; a[S] = INF;
while(q.size()){
int u = q.front(); q.pop(); vis[u] = false;
for(int i = head[u]; ~i; i = edges[i].nxt){
Edge &e = edges[i];
if(e.cap && d[e.v] > d[u]+e.cost){
d[e.v] = d[u] + e.cost;
p[e.v] = i;
a[e.v] = min(e.cap,a[u]);
if(!vis[e.v]){
vis[e.v] = true;
q.push(e.v);
}
}
}
}
if(d[T] == INF) return flow;
flow += a[T];
cost += a[T]*d[T];
for(int i = T; i != S; i = edges[p[i]^].v){
edges[p[i]].cap -= a[T];
edges[p[i]^].cap += a[T];
}
}
return -;
} void init()
{
memset(head,-,sizeof(int)*vcnt);
edges.clear();
} int main()
{
//freopen("in.txt","r",stdin);
int n;
S = ;
while(scanf("%d",&n),n){
vcnt = *n+;
init(); T = *n+;
for(int i = ; i <= n; i++){
AddEdge(S,i,,);
AddEdge(i+n,T,,);
}
for(int i = ; i <= n; i++){
int v,c;
while(scanf("%d",&v),v){
scanf("%d",&c);
AddEdge(i,v+n,,c);
}
}
int cost;
int flow = MCMF(cost);
if(flow<n) puts("N");
else printf("%d\n",cost);
}
return ;
}