随笔分类 - 图论
摘要:#include "iostream"#include "cstdio"#include "cstring"#include "queue"#include "algorithm"using namespace std;#define mem(a,y) memset(a,y,sizeof(a))#define inf 0x7f7f7f7fconst int maxn = 1100;const int maxm = 30000;struct node{ int v,len,next;}edge[m
阅读全文
摘要:给定一个有向图,问最少增加多少条边后变成强连通图 tarjan求求强连通分量并缩点,如果强连通分量个数为1,则需要边数为0, 否则为缩点后点入度和出度的最大值, 证明:当入度或者出度不为0时,则可以通过传递性使其相同,所以只需要考虑入度或者出度为0的点 即可。因为要求增加尽量少的边,所以将入度和出度都为0的点相连,边的方向为出度为0的指向入度为0的顶点。 当入度为0或者出度为0的点有剩余时,则任意取一个点进行连边。 所以当有向图为强连通图时答案为0,否则最小值为入度和入度的最大值#include #include #include #include using names...
阅读全文
摘要:题意:给定一个图,求从1到N的递增边权的最短路。解法:类似于bellman-ford思想,将所有的边先按照权值排一个序,然后依次将边加入进去更新,每条边只更新一次,为了保证得到的路径是边权递增的,每次将相同权值的边全部取出来一同更新,每条边能够更新的前提是某一个端点在之前被更小的边权更新过。另外一个要注意的地方就是一次相同边的更新中,要把所有的更新暂存起来最后一起去更新,这样是为了防止同一权值的边被多次加入到路径中去。#include #include #include #include #include #include using namespace std;typedef __int64
阅读全文
摘要:#include #include #include #include #include using namespace std;const int maxn = 16100;struct node { int v,next;} edge[41000];int head[maxn],sta[maxn],vis[maxn];int id,top,n;void add_edge(int u,int v){ edge[id].v = v;edge[id].next = head[u];head[u] = id++;}int dfs(int u){ if( vis[u^1] )r...
阅读全文
摘要:#include#include#include#include#include#includeusing namespace std;int const oo = 100000000;int cost[103][103]; // 花费=边 int used[103][103]; // 表示这条边是否在生成树中 int father[103]; // 生成树中点的 int maxlen[103]; // 表示i点到根的路径上除了与根直接相连的边外,边权最大的边的边权。int vis[103]; // 标记 int d[103]; // 求最...
阅读全文
摘要:=============== 分割线之下摘自Sasuke_SCUT的blog=============最 小树形图,就是给有向带权图中指定一个特殊的点root,求一棵以root为根的有向生成树T,并且T中所有边的总权值最小。最小树形图的第一个算法是 1965年朱永津和刘振宏提出的复杂度为O(VE)的算法。 判断是否存在树形图的方法很简单,只需要以v为根作一次图的遍历就可以了,所以下面的 算法中不再考虑树形图不存在的情况。 在所有操作开始之前,我们需要把图中所有的自环全都清除。很明显,自环是不可能在任何一个树形图上的。只有进 行了这步操作,总算法复杂度才真正能保证是O(VE)。 首先为除根之外
阅读全文
摘要:可以把一对夫妇当成一个节点,然后拆点的话,h和w分别为真和假,然后直接按照题目中说的建图染色即可#include #include #include #include #include #include using namespace std;const int maxn = 100;const int maxm = 1000;struct node{ int v,next;}edge[maxm];int res[maxm][2],head[maxn],low[maxn],dfn[maxn],stack[maxn],in[maxn],fa[maxn],ha[maxn];int colo...
阅读全文
摘要:#include #include #include #include #include using namespace std;const int maxn = 1000;const int maxm = 100000;const int inf = 10000000;struct node{ int v,flow,next;}edge[maxm];int head[maxn],dis[maxn];int id,s,t,n,m;void add_edge(int u,int v,int flow){ edge[id].v = v;edge[id].flow = flow;edge...
阅读全文
摘要:由于被小孩子不喜欢的糖果的对小孩产生的效力是一样的,所以我们在网络流的时候先不考虑。1 - 源点0到1~N个糖果,容量为1,费用为02 - 根据like数组,like[i][j] == 1时在糖果j和人N+i之间建立有一条边,容量为1,费用为03*- 根据b[i]和K的值建立小孩和汇点之间的边:如果b[i] 是 K 的倍数, 说明花费b[i] / K个喜欢的糖果可以达到b[i],建立一条边,费用为K,容量为b[i] / K;否则,将这条边拆为两部分,第一部分是b[i] / K的部分,第二部分根据b[i] % K的部分。(如果b[i] % k == 0,说明b[i]是k的倍数;若b[i]...
阅读全文
摘要:/*** 无向图拆点,求最大流,最大流即为割点个数。*/#include #include #include #include #include using namespace std;const int maxn = 410;const int maxm = 100100;const int INF = 200000000;struct node{ int v,flow,next;}edge[maxm];int head[maxn],dis[maxn],aug[maxn];int n,m,s,t,id;void add_edge(int u,int v,int flow){ e...
阅读全文
摘要:题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2485题目要求:删除最少的点,使得源点到汇点的距离大于k思路:拆点、建图求费用小于等于k的最大流#include #include #include #include #include using namespace std;#define min(x,y) (x)que; que.push(source); while( !que.empty()){ int u = que.front(); que.pop(); vis[u] = 0; ...
阅读全文
摘要:#include #include #include #include #include using namespace std;const int maxm = 50000*4;const int maxn = 110;struct node{ int v,cost,flow,next;//v表示指向的下一个顶点,a表示系数,flow表示可以过的流量}edge[maxm];int head[maxn],dis[maxn],pre[maxn],cur[maxn],vis[maxn],aug[maxn];int s,t,v,n,m,k,id,flow;void add_edge(int u...
阅读全文
摘要:一开始题目没看清楚,以为是增加那条边后还有多少桥,所以就当做是无向图tarjan缩点后建树,然后求u,v的最近公共祖先,一直wa。后来再看题目后才发现边放上去后不会拿下来了,即增加i条边后桥的数量。#include #include #include #include using namespace std;const int maxn = 100100;const int maxm = 200100;struct node{ int v,next;}edge[maxm*2];int head[maxn],low[maxn],dfn[maxn],fa[maxn],stack[maxn]...
阅读全文
摘要:/*** 题目要求过最少k条边的最短路*/#include #include #include #include #include using namespace std;const int maxn = 5010;const int maxm = 200010;const int INF = 1que; tmp.v = s,tmp.num = 0; dp[tmp.v][tmp.num] = 0; vis[tmp.v][tmp.num] = 1; que.push(tmp); while( !que.empty()){ now = que.front...
阅读全文
摘要:#include #include #include using namespace std;const int maxn = 2100;struct node{ int v,next;}edge[maxn*maxn];int head[maxn],res[1005*1005][2],low[maxn],dfn[maxn],stack[maxn],in[maxn];int n,m,id,clock,top;void add_edge(int u,int v){ edge[id].v = v;edge[id].next = head[u];head[u] = id++;}void i...
阅读全文
摘要:题目意思:给出n个点,m条边,边分为两种,一种是A公司的,一种是B公司的。边上有权值,问用n-1条边把n个点连起来的最小费用是多少,其中A公司的边刚好有k条。题目保证有解。题解:题目意思很简单就是求MST且A公司要有且仅有k条边在树中,刚开始做的时候用贪心的方式求最小生成树结果WA,后来看了下别人的题解,二分出一个最大值delta使得A公司的边加上这个值后再求MST时A公司的边有大于等于k条,然后答案就是cost of MST - k * delta。思想就是用一个delta去逼近答案。当delta越大的时候A公司的边就越少,反之越多。所以二分delta可以找到使得A公司刚好取K条边的要求。#
阅读全文
摘要:题意: 莱克尔和她的朋友到公园玩,公园很大也很漂亮。公园包含n个景点通过n-1条边相连。克莱尔太累了,所以不能去参观所有点景点。经过深思熟虑,她决定只访问其中的k个景点。她拿出地图发现所有景点的入口都很特殊。所以她想选择一个入口,并找到一条最短的路来参观k个景点。我们假设景点之间的距离为1。解题思路:因为地图形状为树形,所以求树的最大直径。当k小于等于直径的时候输出k-1,当k大于直径的时候,因为访问了某一个景需要返回直径所在的路径上,所以当k大于冷的时候结果为len-(k-len-1)*2。#include #include #include #include #include using
阅读全文
摘要:#pragma comment(linker,"/STACK:102400000,102400000")#include #include #include #include #include #include using namespace std;const int maxn = 200100;const int maxm = 2000100;struct node{ int v,next;}edge[maxm];struct Bridge{ int u,v;}bridge[maxm];int head[maxn],vis[maxm],fa[maxn],dfn[maxn
阅读全文
摘要:题意: 平面上,一个圆,圆的边上按顺时针放着n个点。现在要连m条边,比如a,b,那么a到b可以从圆的内部连接,也可以从圆的外部连接。给你的信息中,每个点最多只会连接的一条边。问能不能连接这m条边,使这些边都不相交。解题报告:题意可能刚开始不是很好理解,比如1 5连边,2,6连边,由于点是顺序排列的,一画图就可以发现,这两条边必须一个从圆外面连,一个从内部连,否则就会相交。如果再加入3 7这条边,那么就必须相交了。这样,就可以转化成标准的2-sta问题:1:每个边看成2个点:分别表示在内部连接和在外部连接,只能选择一个。计作点i和点i'2:如果两条边i和j必须一个画在内部,一个画在外部(
阅读全文
摘要:第一次按常规的方法求,将所有的查询的u,v,和最近公共祖先都保存起来,然后用tarjan+并查集求最近公共祖先。因为询问的次数过多,所以在保存查询的时候总是MLE,后来参考了一下别人的代码,才突然觉悟,可以先将u,v,和其最近公共祖先保存到数组,然后再求结果,为什么不能直接保存其结果了。如果只保存结果的话,保存查询操作就可以节约1/3的内存,所以基本可以过了。代码如下:方法一:#include #include #include #include #include using namespace std;const int maxn = 10100;vector >tree[maxn],
阅读全文

浙公网安备 33010602011771号