思路:如果乙個dag要的路徑上只要一條邊去切掉,那麼要怎麼求?很容易就想到最小割,但是如果直接做最小割會走出重複的部分,那我們就這樣:反向邊設為inf,這樣最小割的時候就不會割到了,判斷無解我們直接用tarjan
1 #include2 #include3 #include4 #include5 #include6#define ll long long
7const ll inf = 1ll << 60;8
struct
edgee[200005
];11 ll flow[200005
];12
int op[200005],dis[200005],cnt[200005],a[115][115],pd[10005
];13
int tot,go[200005],next[200005],first[200005
],s,t,nodes,sz;
14int n,m,vis[200005],instack[200005],c[200005],top,dfn[200005],low[200005],belong[200005
],num;
15int
read()
18while ('0'
<=ch&&ch<='9')
19return t*f;20}
21void insert(int x,int
y)27
void insert(int x,int
y,ll z)
34void add(int x,int
y,ll z)
38void tarjan(int
x)else
if(instack[pur])49}
50if (low[x]==dfn[x])
57 belong[c[top]]=num;
58 instack[c[top]]=0
;59 top--;60}
61}62 ll dfs(int
x,ll f)
75if (flow[i]) mn=std::min(mn,dis[pur]);76}
77if (sum==0
)else85}
86return
sum;87}
88int
main()
95for (int i=1;i<=n;i++)
96if (!vis[i]) tarjan(i);
97if (belong[1]==belong[n])
101for (int i=1;i<=n;i++)
102 a[i][i]=1
;103
for (int k=1;k<=n;k++)
104for (int i=1;i<=n;i++)
105for (int j=1;j<=n;j++)
106 a[i][j]|=a[i][k]&&a[k][j];
107for (int i=1;i<=n;i++)
108if (a[1][i]&&a[i][n]) pd[i]=1
;109
for (int i=1;i<=m;i++)
110if (pd[e[i].u]&&pd[e[i].v])
111add(e[i].u,e[i].v,e[i].w);
112 s=1;t=n;nodes=n;
113int ans=0
;114
while (dis[s]dfs(s,inf);
115if (ans==0) printf("-1"
);116
else printf("
%d\n
",ans);
117 }
FJ省隊集訓DAY3 T1
思路 我們考慮如果取掉乙個部分,那麼能影響到最優解的只有離它最近的那兩個部分。我講的貌似不是很清楚。還有,蜜汁80分,打死也改不出來。1 include2 include3 include4 include5 include6 struct nodea 1200005 9 struct segmen...
FJ省隊集訓DAY1 T1
題意 有一堆兔子,還有乙個r為半徑的圓,要求找到最大集合滿足這個集合裡的兔子兩兩連邊的直線不經過圓。思路 發現如果有兩個點之間連邊不經過圓,那麼他們到圓的切線會構成一段區間,那麼這兩個點的區間一定會有交集,形如s0 s1 e0 e1 同樣的,如果是n個點,那就是s0 s1 s2.sn e0 e1 e...
省隊集訓Round2 DAY3
用splay維護權值有序。每次加入乙個人,貪心的選出前i 1個人中要求最小的vi 1,判斷能否滿足,如果能滿足就把這vi 1個人的權值 1,剩下的人不需要他們的支援,那麼都賦值成0,並且把這些點移動到平衡樹中0所在的位置 如果不能滿足就直接在平衡樹中加入乙個 1.要求每乙個時間每條邊只能有乙個人經過...