上机考试资料
最长不下降子序列
正一遍反一遍求子序列就行。
#include <bits/stdc++.h>
using namespace std;
#define N 101
#define ll long long
template <class T>
inline T read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
a = x * s;
return a;
}
int n;
int a[N];
int b[N];
int dp1[N], dp2[N];
int main(){
//freopen("hh.txt", "r", stdin);
cin >> n;
for(int i = 1; i <= n; i++)
cin >> a[i];
for(int i = 1; i <= n; i++)
b[i] = a[n - i + 1];
int ans = 1e9;
for(int top = 0; top <= n + 1; top++){
memset(dp1, 0, sizeof(dp1));
memset(dp2, 0, sizeof(dp2));
int maxn1 = 0, maxn2 = 0;
for(int i = 1; i <= top; i++){
dp1[i] = 1;
dp2[i] = 1;
for(int j = 1; j < i; j++){
if(a[i] > a[j]) dp1[i] = max(dp1[i], dp1[j] + 1);
}
}
for(int i = 1; i <= n - top + 1; i++){
dp2[i] = 1;
for(int j = 1; j < i; j++)
if(b[i] > b[j]) dp2[i] = max(dp2[i], dp2[j] + 1);
}
ans = min(ans, n - dp1[top] - dp2[n - top + 1] + 1);
}
cout << ans << endl;
return 0;
}
最小生成树
#include <bits/stdc++.h>
using namespace std;
#define N 101
#define ll long long
template <class T>
inline T read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
a = x * s;
return a;
}
int n;
int dis[N][N];
struct node{
int u, v, w;
bool operator < (const node &a) const{
return w < a.w;
}
} t[N * N];
int fa[N];
int find_fa(int x){
return x == fa[x] ? x : fa[x] = find_fa(fa[x]);
}
bool issame(int u, int v){
return find_fa(u) == find_fa(v);
}
void merge(int u, int v){
int fau = find_fa(u), fav = find_fa(v);
if(fau != fav) fa[fau] = fav;
return ;
}
int cnt = 0;
int kruskal(){
int sum = 0;
sort(t + 1, t + cnt + 1);
for(int i = 1; i <= cnt; i++){
int u = t[i].u, v = t[i].v;
if(!issame(u, v)){
merge(u, v);
sum += t[i].w;
}
}
return sum;
}
int main(){
//freopen("hh.txt", "r", stdin);
read(n);
for(int i = 1; i <= n; i++)
fa[i] = i;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
read(dis[i][j]);
t[++cnt] = (node){i, j, dis[i][j]};
}
}
cout << kruskal() << endl;
return 0;
}
二分图最大匹配(旬牙利算法)
#include <bits/stdc++.h>
using namespace std;
#define N 700010
inline int read(){
int x = 0,s = 1;
char c = getchar();
while(c < '0' || c > '9'){
if(c == '-')s = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
x = (x << 1) + (x << 3) + (c ^ '0');
c = getchar();
}
return x * s;
}
int n,m,e;
int f[N];
struct node{
int u,v,next;
} t[N];
int ti = 1,ans = 0;
int match[N];
int dfn[N];
bool vis[N];
int cnt = 0;
void add(int u,int v){
cnt++;
t[cnt].v = v;
t[cnt].u = u;
t[cnt].next = f[u];
f[u] = cnt;
return;
}
bool dfs(int now,int ti){
for(int i = f[now]; i;i = t[i].next){
int v = t[i].v;
if(dfn[v] != ti){
dfn[v] = ti;
if(!match[v] || dfs(match[v],ti)){
match[v] = t[i].u;
return 1;
}
}
}
return 0;
}
int main(){
// freopen("hh.txt","r",stdin);
n = read(),m = read(),e = read();
for(int i = 1;i <= e; i++){
int u = read(),v = read();
if(u > n || v > m)continue;
add(u,v);
}
for(int i = 1;i <= n; i++)
if(dfs(i,++ti))ans++;
printf("%d",ans);
return 0;
}
网络最大流 (Dicnic)
#include<bits/stdc++.h>
using namespace std;
#define N 500010
#define ll long long
const ll INF = ~0u >> 1;
inline ll read(){
ll x = 0,s = 1;
char c = getchar();
while(!isdigit(c)){
if(c == '-')s = -1;
c= getchar();
}
while(isdigit(c)){
x = x * 10 + c - '0';
c = getchar();
}
return x * s;
}
struct node{
ll u,v,next = -1,w;
} t[N];
ll n,m,s,ht;
ll f[N],cur[N];
ll deth[N];
ll cnt = -1;
void add(ll u,ll v,ll w){
cnt++;
t[cnt].u = u;
t[cnt].v = v;
t[cnt].w = w;
t[cnt].next = f[u];
f[u] = cnt;
return;
}
bool vis[N];
queue <ll> q;
void clean2(){
memset(deth,0,sizeof(deth));
while(!q.empty())q.pop();
return;
}
bool bfs(){
clean2();
q.push(s);
deth[s] = 1;
while(!q.empty()){
ll now = q.front();
q.pop();
for(ll i = f[now];i != -1; i = t[i].next) {
ll v = t[i].v,w = t[i].w,u = t[i].u;
if(!deth[v] && w != 0){
deth[v] = deth[u] + 1;
q.push(v);
}
}
}
if(deth[ht])
return 1;
else return 0;
}
ll dfs(ll now,ll dist){
if(now == ht)return dist;
for(ll& i = cur[now];i != -1; i = t[i].next){
cur[now] = i; // 当前弧优化
ll v = t[i].v;
if(deth[v] == deth[now] + 1 && t[i].w != 0){
ll di = dfs(v, min(dist, t[i].w));
if(di > 0){
t[i].w -= di;
t[i^1].w += di;
return di;
}
}
}
return 0;
}
ll answer(){
ll ans = 0;
while(bfs()){
memcpy( cur, f, sizeof(cur) );
while(ll temp = dfs(s,INF))
ans += temp;
}
return ans;
}
void clean(){
cnt = -1;
memset(f,-1,sizeof(f));
return;
}
int main(){
//freopen("hh.txt","r",stdin);
n = read(),m = read(),s = read(),ht = read();
clean();
for(ll i = 0;i < m; i++){
ll x = read(),y = read(),z = read();
add(x,y,z);
add(y,x,0);//加虚边
}
printf("%lld",answer());
return 0;
}
差分约束
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long
template <class T>
inline void read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
a = x * s;
return ;
}
struct node{
int u, v, w, next;
} t[N];
int head[N];
int bian = 0;
inline void addedge(int u, int v, int w){
t[++bian] = (node){u, v, w, head[u]}, head[u] = bian;
// t[++bian] = (node){v, u, w, head[v]}, head[v] = bian;
return ;
}
int n, m;
int in[N];
int cac[N];
ll dis[N];
bool vis[N];
int spfa(int s){
queue <int> q;
q.push(s);
for(int i = 0; i <= n; i++){
dis[i] = 1e9;
}
dis[s] = 0;
while(!q.empty()){
int u = q.front(); q.pop();
vis[u] = 0;
// cac[u]++;
// if(cac[u] == n) return -1;
for(int i = head[u]; i; i = t[i].next){
int v = t[i].v;
if(dis[v] >= dis[u] + t[i].w){
dis[v] = dis[u] + t[i].w;
if(!vis[v]) q.push(v), vis[v] = 1;
}
}
}
return 1;
}
int main(){
//freopen("hh.txt", "r", stdin);
read(n), read(m);
for(int i = 1; i <= m; i++){
int x, y, w;
read(x), read(y), read(w);
addedge(y, x, w); // x - y <= w -> x <= y + w -> y连x求最短路。最长路情况同理。二者可以加负号转换
}
for(int i = 1; i <= n; i++){
addedge(0, i, 0);
}
spfa(0);
for(int i = 1; i <= n; i++)
cout << dis[i] << " ";
return 0;
}