bupt summer training for 16 #6 ——图论
https://vjudge.net/contest/174020
A.100条双向边,每个点最少连2个边
所以最多100个点,点的标号需要离散化
然后要求恰好经过n条路径
快速幂,乘法过程就是floyed就行了
#include <algorithm>
#include <cstring>
#include <cstdio> using namespace std; const int maxn = ; int n, m, s, t, b, c[]; struct matrix {
int c[][];
matrix() {
memset(c, 0x3f, sizeof c);
}
void add(int u, int v, int w) {
c[u][v] = c[v][u] = w;
}
matrix operator * (const matrix &a) const {
matrix b;
for(int k = ;k <= n;k ++)
for(int i = ;i <= n;i ++)
for(int j = ;j <= n;j ++)
b.c[i][j] = min(b.c[i][j], c[i][k] + a.c[k][j]);
return b;
}
matrix operator ^ (int &k) {
matrix b = *this;
for(k --;k > ;k >>= , *this = (*this) * (*this))
if(k & ) b = b * (*this);
return b;
}
}; int main() {
matrix g;
int u, v, w;
scanf("%d %d %d %d", &n, &m, &s, &t);
while(m --) {
scanf("%d %d %d", &w, &u, &v);
if(!c[u]) c[u] = ++ b;
if(!c[v]) c[v] = ++ b;
g.add(c[u], c[v], w);
}
swap(b, n);
printf("%d", (g ^ b).c[c[s]][c[t]]);
return ;
}
B.
C.非常裸的生成树计数问题
其实谁是最高管理层并没什么卵用
想当然理解了读入,垃圾题目有重边
注意有重边,整数行列式计算可以拿来当板子了
#include <algorithm>
#include <cstring>
#include <cstdio> using namespace std; const int maxn = ; int n, m, s, t, b, c[]; struct matrix {
int c[][];
matrix() {
memset(c, 0x3f, sizeof c);
}
matrix(int x) {
memset(c, , sizeof c);
for(int i = ;i <= n;i ++)
c[i][i] = ;
}
void add(int u, int v, int w) {
c[u][v] = c[v][u] = w;
}
matrix operator * (const matrix &a) const {
matrix b;
for(int k = ;k <= n;k ++)
for(int i = ;i <= n;i ++)
for(int j = ;j <= n;j ++)
b.c[i][j] = min(b.c[i][j], c[i][k] + a.c[k][j]);
return b;
}
matrix operator ^ (int &k) {
matrix b = *this;
for(k --;k > ;k >>= , *this = (*this) * (*this))
if(k & ) b = b * (*this);
return b;
}
}; int main() {
matrix g;
int u, v, w;
scanf("%d %d %d %d", &n, &m, &s, &t);
while(m --) {
scanf("%d %d %d", &w, &u, &v);
if(!c[u]) c[u] = ++ b;
if(!c[v]) c[v] = ++ b;
g.add(c[u], c[v], w);
}
swap(b, n);
printf("%d", (g ^ b).c[c[s]][c[t]]);
return ;
}
D.
E.高中做过的网络流模型
每行被隔开的算一块,st向这些块连边流量为1
因为这样一个块里最多放一个棋子
每列被隔开的算一块,这些块向en连边流量为1,道理同上
行块和列快相遇出可以放旗子,那么它们连一条边流量为1
因为只有一个位置
求个最大流...这样一说直接二分图上匈牙利就可以了...
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; const int maxn = , maxm = , inf = 0x3f3f3f3f; int s, t, len = , g[maxn]; struct edge {
int to, cap, next;
}e[maxm]; int p[maxn], q[maxn], d[maxn]; void add(int u, int v, int w) {
e[++ len] = (edge){v, w, g[u]}, g[u] = len;
e[++ len] = (edge){u, , g[v]}, g[v] = len;
} bool bfs() {
int l = , r = , x, i;
memset(d, , sizeof d);
d[s] = , q[] = s;
while(l <= r) {
x = q[l ++];
for(i = g[x];i;i = e[i].next)
if(e[i].cap && !d[e[i].to])
d[e[i].to] = d[x] + , q[++ r] = e[i].to;
}
return d[t];
} int dfs(int x, int y) {
if(x == t || y == ) return y;
int flow = ;
for(int &i = p[x];i;i = e[i].next) {
if(!e[i].cap || d[e[i].to] != d[x] + ) continue;
int f = dfs(e[i].to, min(y, e[i].cap));
flow += f, y -= f;
e[i].cap -= f, e[i ^ ].cap += f;
if(!y) break;
}
return flow;
} int dinic() {
int maxflow = ;
while(bfs()) {
memcpy(p, g, sizeof g);
maxflow += dfs(s, inf);
}
return maxflow;
} int n, m, cnt; char str[][]; int mmp[][]; int main() {
t = ;
while(~scanf("%d", &n)) {
m = ;
memset(g, , sizeof g);
for(int i = ;i <= n;i ++)
scanf("%s", str[i] + );
for(int i = ;i <= n;i ++) {
for(int j = ;j <= n;j ++) {
if(str[i][j] == 'X') mmp[i][j] = -;
else {
if(j == || str[i][j - ] == 'X') m ++, add(s, m, );
mmp[i][j] = m;
}
}
}
for(int j = ;j <= n;j ++)
for(int i = ;i <= n;i ++) {
if(str[i][j] != 'X') {
if(i == || str[i - ][j] == 'X') m ++, add(m, t, );
add(mmp[i][j], m, inf);
}
}
printf("%d\n", dinic());
}
}
F.裸的最短路,当然你要看到这是
单向边!!!
#include <queue>
#include <cstdio>
#include <vector>
#include <algorithm> using namespace std; const int maxn = ; queue <int> q; int n, m, k, t, d[maxn], vis[maxn]; vector <pair<int, int> > e[maxn]; int main(){
while(~scanf("%d %d %d", &n, &m, &k)) {
for(int i = ;i <= n;i ++) d[i] = 0x3f3f3f3f, e[i].clear();
for(int u, v, w, i = ;i <= m;i ++) {
scanf("%d %d %d", &u, &v, &w);
e[u].push_back(make_pair(v, w));
//e[v].push_back(make_pair(u, w));
}
scanf("%d", &t);
for(int j, i = ;i <= t;i ++)
scanf("%d", &j), d[j] = , q.push(j);
while(!q.empty()) {
int u = q.front();
q.pop(), vis[u] = ;
for(int i = ;i < e[u].size();i ++) {
if(d[e[u][i].first] > d[u] + e[u][i].second) {
d[e[u][i].first] = d[u] + e[u][i].second;
if(!vis[e[u][i].first]) vis[e[u][i].first] = , q.push(e[u][i].first);
}
}
}
printf("%d\n", d[k] == 0x3f3f3f3f ? - : d[k]);
}
return ;
}
G.裸MST,稠密图没有卡 Kruskal,良心!
#include <cstdio>
#include <algorithm> using namespace std; struct edge {
int u, v, w;
bool operator < (const edge &a) const {
return w < a.w;
}
}e[]; int n, f[]; int find_(int x) {
if(f[x] != x) return f[x] = find_(f[x]);
return x;
} int main() {
while(~scanf("%d", &n)) {
int m = , ans = ;
for(int k, i = ;i <= n;i ++) {
f[i] = i;
for(int j = ;j <= i;j ++) scanf("%d", &k);
for(int j = i + ;j <= n;j ++) scanf("%d", &k), e[++ m] = (edge){i, j, k};
}
sort(e + , e + m + );
for(int u, v, i = , j = ;j < n;i ++) {
u = find_(e[i].u), v = find_(e[i].v);
if(u == v) continue;
f[v] = u, j ++, ans += e[i].w;
}
printf("%d\n", ans);
}
return ;
}
H.
I.经典网络流模型
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; const int maxn = , maxm = , inf = 0x3f3f3f3f; int s, t, len = , g[maxn]; struct edge {
int to, cap, next;
}e[maxm]; int p[maxn], q[maxn], d[maxn]; void add(int u, int v, int w) {
e[++ len] = (edge){v, w, g[u]}, g[u] = len;
e[++ len] = (edge){u, , g[v]}, g[v] = len;
} bool bfs() {
int l = , r = , x, i;
memset(d, , sizeof d);
d[s] = , q[] = s;
while(l <= r) {
x = q[l ++];
for(i = g[x];i;i = e[i].next)
if(e[i].cap && !d[e[i].to])
d[e[i].to] = d[x] + , q[++ r] = e[i].to;
}
return d[t];
} int dfs(int x, int y) {
if(x == t || y == ) return y;
int flow = ;
for(int &i = p[x];i;i = e[i].next) {
if(!e[i].cap || d[e[i].to] != d[x] + ) continue;
int f = dfs(e[i].to, min(y, e[i].cap));
flow += f, y -= f;
e[i].cap -= f, e[i ^ ].cap += f;
if(!y) break;
}
return flow;
} int dinic() {
int maxflow = ;
while(bfs()) {
memcpy(p, g, sizeof g);
maxflow += dfs(s, inf);
}
return maxflow;
} int Case, n, m, sum; int main() {
scanf("%d", &Case);
for(int tt = ;tt <= Case;tt ++) {
sum = , len = ;
memset(g, , sizeof g);
printf("Case #%d: ", tt);
scanf("%d %d", &n, &m), t = n + m + ;
for(int j, i = ;i <= n;i ++)
scanf("%d", &j), add(s, i, j), sum += j;
for(int j, i = ;i <= m;i ++)
scanf("%d", &j), add(n + i, t, j);
for(int k, j, i = ;i <= n;i ++) {
scanf("%d", &k);
while(k --) {
scanf("%d", &j);
add(i, n + j + , inf);
}
}
for(int k, i = ;i <= m;i ++)
for(int j = ;j <= m;j ++) {
scanf("%d", &k);
if(k) add(n + i, n + j, inf);
}
printf("%d\n", sum - dinic());
}
return ;
}
J.随便做的傻逼题,我写的算麻烦的
#include <cstdio>
#include <algorithm> using namespace std; int n, a[]; int main() {
scanf("%d", &n);
for(int i = ;i <= n;i ++)
scanf("%d", &a[i]);
int l = , r = n;
while(!a[l] && l <= n) l ++;
while(!a[r] && r >= ) r --;
if(l > r) puts("");
else {
int ans = , last = ;
for(int i = l + ;i <= r;i ++) {
if(a[i]) {
ans ++;
if(last != ) last = ;
}
else {
if(last != ) {
if(i < r && !a[i + ]) last = ;
else ans ++;
}
}
}
printf("%d\n", ans);
}
return ;
}
bupt summer training for 16 #6 ——图论的更多相关文章
- bupt summer training for 16 #8 ——字符串处理
https://vjudge.net/contest/175596#overview A.设第i次出现的位置左右端点分别为Li,Ri 初始化L0 = 0,则有ans = sum{ (L[i] - L[ ...
- bupt summer training for 16 #7 ——搜索与DP
https://vjudge.net/contest/174962#overview A.我们发现重点在于x,y只要累加就ok了 在每个x上只有上下两种状态,所以可以记忆化搜索 f[0/1][i]表示 ...
- bupt summer training for 16 #5 ——数据结构
https://vjudge.net/contest/173780 A.假设 Pt = i,则由Ppi = i得 Ppt = t = Pi 所以就有 if Pt = i then Pi = t #in ...
- bupt summer training for 16 #4 ——数论
https://vjudge.net/contest/173277#overview A.平方差公式后变为 n = (x + y)(x - y) 令 t = x - y ,变成 n = (t + 2x ...
- bupt summer training for 16 #3 ——构造
https://vjudge.net/contest/172464 后来补题发现这场做的可真他妈傻逼 A.签到傻逼题,自己分情况 #include <cstdio> #include &l ...
- bupt summer training for 16 #2 ——计算几何
https://vjudge.net/contest/171368#overview A.一个签到题,用叉积来判断一个点在一条线的哪个方向 可以二分,数据范围允许暴力 #include <cst ...
- bupt summer training for 16 #1 ——简单题目
D.What a Mess 给n个数,求其中能满足 a[i] % a[j] == 0 的数对之和 n = 1W,max_ai = 100W 不是很大,所以就直接筛就可以了 计算可得最高复杂度 < ...
- 【Android Developers Training】 16. 暂停和恢复一个Activity
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- BUPT2017 springtraining(16) #6 ——图论
题目链接 A.容易发现最后字符的对应都是一对一的 或者说我们没办法出现最后多对一或者一对多的情况 所以只要算出 ‘a’ - 'z' 每个字符最后对应的字符即可 #include <cstdio& ...
随机推荐
- hdoj--5611--Baby Ming and phone number(模拟水题)
Baby Ming and phone number Crawling in process... Crawling failed Time Limit:1500MS Memory Li ...
- input如何去掉边框
outline: none; border:solid 0px; 两个属性,ok.
- [Apple开发者帐户帮助]九、参考(5)支持的功能(tvOS)
tvOS应用程序可用的功能取决于您的程序成员身份. 能力 ADP 企业 Apple开发者 应用程序组 相关域名 背景模式 数据保护 游戏中心 游戏控制器 HomeKit iCloud:Cl ...
- xfs文件备份恢复篇一vm中linux新增磁盘
XFS提供了 xfsdump 和 xfsrestore 工具协助备份XFS文件系统中的数据.xfsdump 按inode顺序备份一个XFS文件系统.centos7选择xfs格式作为默认文件系统,而且不 ...
- IOS上微信在输入框弹出键盘后,页面不恢复,下方有留白,有弹窗弹出时页面内容感应区域错位
问题说明: ios中,键盘的弹起,页面会往上挪动,使输入框展示在页面中间,键盘隐藏页面会下挪恢复原状. 在微信移动端,ios页面不恢复,下方有留白. 收起键盘的瞬间,如果有弹窗弹出,此时时页面内容应区 ...
- mysql在linux下的安装(5.7版本以后)
1.添加mysql组和mysql用户,用于设置mysql安装目录文件所有者和所属组. ①groupadd mysql ②useradd -r -g mysql mysql 2.将二进制文件解压到指定的 ...
- 【知识总结】多项式全家桶(一)(NTT、加减乘除和求逆)
我这种数学一窍不通的菜鸡终于开始学多项式全家桶了-- 必须要会的前置技能:FFT(不会?戳我:[知识总结]快速傅里叶变换(FFT)) 以下无特殊说明的情况下,多项式的长度指多项式最高次项的次数加\(1 ...
- 【转】mysql的数据类型
转自:http://mrxiong.blog.51cto.com/287318/1651098 一.数值类型 Mysql支持所有标准SQL中的数值类型,其中包括严格数据类型(INTEGER,SMALL ...
- 【原】cocos2d-x开发笔记:获取Sprite上某一个点的透明度,制作不规则按钮
本篇文章主要讲一下怎么做一个不规则的按钮,比如如下图的八卦,点击绿色和点击红色部分,需要执行不同的事件
- Linux 信息查询
CPU信息查看 #查看CPU型号: $>grep 'model name' /proc/cpuinfo |uniq model name : Intel(R) Xeon(R) CPU ...