2017华为软挑---SPFA、ZKW、模拟退火

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

------------------------核心---------------------

deploy.h

#ifndef __ROUTE_H__
#define __ROUTE_H__

#include "lib_io.h"
#include "lib_time.h"

#include "string.h"
#include "stdlib.h"
#include "time.h"
//#include <sys/time.h>
#include "iostream"
#include "fstream"
#include "vector"
#include "queue"
#include "algorithm"
#include "map"
#include "set"
#include "sstream"
using namespace std;

void deploy_server(char * graph[MAX_EDGE_NUM], int edge_num, char * filename);

#define INF  2000000000
#define INT_MAX  2000000000
#define INT_MAX1  2000000000
#define MAX_netNodeCnt       1002    // 网络节点最大数+2
#define MAX_consumeNodeCnt   500     // 消费节点最大数
#define MAX_linkeCnt         20000   // 链路最大数

struct Edge
{
	//int from;      // 链路起始节点ID
	int to;          // 链路终止节点ID
	int cap;         // 总带宽
	int cost;        // 单位带宽租用费
	int flow;        
	int next;
};

// 消费节点信息
struct ConsumeNode
{
	int ID;          // 消费节点ID
	int netID;       // 相连网络节点ID
	int demand;      // 视频带宽需求
};

// 用于结果输出
struct Result
{
	vector<int> path;     // 路径
	int flow;             // 占用带宽
	Result()
	{
		path.clear();
		flow = 0;
	}
};

struct Node
{
	int id;          // 网络节点ID 
	int degree;      // 度 
	
	Node()
	{
		id = 0;
		degree = 0;
	}
	
	bool operator < (const struct Node &node)const
	{
		return degree > node.degree;
	}
};

void build(char * topo[MAX_EDGE_NUM], int line_num);
void addEdge(int from, int to, int cap, int cost, int &id);
bool min_cost(int &cost, int nEdge, int nServer);    // 最小费用流
void record_result();
void dfs(int u, Result &r, int &flow);   // 搜索路径             
bool min_cost1();  
void record_result1();

///随机算法/


// 个体
class Entity
{
public:
	set<int> position;      // 服务器安放的位置
	int fitness;            // 适应度值,即总的花费
	
	Entity()
	{
		fitness = INT_MAX;
		position.clear();
	}
	
	bool operator < (const Entity &e) const
	{
		return fitness < e.fitness;
	}
	
	int getFit();
	int getFit1();
};

void init();             // 种群初始化  
void mutate();           // 变异函数
void mainEA();           // 随机算法主函数

#endif

deploy.cpp

#include "deploy.h"
#include "algorithm"
#include <stdio.h>

int netNodeCnt;      // 网络节点数量
int linkeCnt;        // 网络链路数量
int consumeNodeCnt;  // 消费节点数量
int serverCost;      // 视频内容服务器部署成本
ConsumeNode consume[MAX_consumeNodeCnt];  // 消费节点信息数组
Edge edge[4*MAX_linkeCnt];                // 链路信息数组
int head[MAX_netNodeCnt];                 
int preV[MAX_netNodeCnt];                 
int preE[MAX_netNodeCnt];
int dist[MAX_netNodeCnt];
bool vis[MAX_netNodeCnt];
int id = 0;                  // 边的ID
int S, T;                    // 超级源点、汇点
int F;                       // 总带宽需求
int minCost = INT_MAX;       // 最小花费
map<int, int> mapConsume;    // 记录网络节点与那个消费节点相连

vector<Result> path;         // 路径
vector<Result> bestPath;     // 最佳路径
string result;               
Entity Best;                 // 最优解个体

double PMUTATION1 = 55;
double PMUTATION2 = 90;
int POPSIZE = 50;
set<int> sChoice;            // 服务器选择范围
vector<int> vChoice;
set<int> bad;                // 禁忌表

int maxflow;
int serverNum;
int cur[MAX_netNodeCnt], pre[MAX_netNodeCnt];

clock_t start, finish;

Node node[MAX_netNodeCnt];

//struct timeval T1, T2, T3; 

double decs = 0.97;
double temp = 150;
double thold = 15;
Entity MostBest;

void solve();

//You need to complete the function 
void deploy_server(char * topo[MAX_EDGE_NUM], int line_num, char * filename)
{
	//gettimeofday(&T1, NULL); 
	build(topo, line_num);
	srand(time(NULL));
	//gettimeofday(&T2, NULL);
	mainEA(); 
	cout << "minCost:" << minCost << endl;
	record_result();
	//write_result(result.c_str(), filename);
}

void addEdge(int from, int to, int cap, int cost, int &id)
{
	edge[id].to = to;
	edge[id].cap = cap;
	edge[id].cost = cost;
	edge[id].flow = 0;
	edge[id].next = head[from];
    head[from] = id++;
}

// 读入文件,建图
void build(char * topo[MAX_EDGE_NUM], int line_num)
{
	memset(head, -1, sizeof(head));
	
	istringstream sin;
	sin.str(topo[0]);
	sin >> netNodeCnt >> linkeCnt >> consumeNodeCnt;
	sin.str(topo[2]);
	sin >> serverCost;
	
	
	// 网络节点之间的边
	int i, from, to, cap, cost;
	for(i=4; i<linkeCnt+4; i++)
	{
		sin.str(topo[i]);
		sin >> from >> to >> cap >> cost;
		addEdge(from, to, cap, cost, id);
		addEdge(to, from, 0,  -cost, id);
		addEdge(to, from, cap, cost, id);
		addEdge(from, to, 0,  -cost, id);
		//cout << from << " " << to << " " << cap << " " << cost << endl;
		
		node[from].id = from;
		node[from].degree++;
		node[to].id = to;
		node[to].degree++;
	}
	
	
	S = netNodeCnt;
	T = S + 1;
	
	// 超级源点与“消费节点连向的网络节点”之间的边
	for(i=0; i<consumeNodeCnt; i++)
	{
		sin.str(topo[i+linkeCnt+5]);
		sin >> consume[i].ID >> consume[i].netID >> consume[i].demand;
		addEdge(S, consume[i].netID, consume[i].demand, 0, id);
		addEdge(consume[i].netID, S, 0, 0, id);
		F += consume[i].demand;
		mapConsume[consume[i].netID] = consume[i].ID;
	}
}

// 记录结果 
void record_result()
{
	ostringstream sout;
	int n = bestPath.size();
	sout << n << "\n" << "\n";
	for (int p = 0; p < n; p++)
	{
		int j;
		
		for(j = bestPath[p].path.size()-2; j >=0; j--)
		{
			sout << bestPath[p].path[j] << " ";
		}
		sout << mapConsume[bestPath[p].path[0]] << " " << bestPath[p].flow;
		if(p != n-1)
			sout << "\n";
	}
	result = sout.str();
	//cout << result << endl;
}

// 最小费用流
bool min_cost(int &cost, int nEdge, int nServer)
{
	queue<int> q;
	int flow = 0;
	cost = serverCost * nServer;
	int i;
	for(i=0; i<nEdge; i++)
		edge[i].flow = 0;
	path.clear();
	
	while(1)
	{
		memset(vis, false, sizeof(vis));
		fill(dist, dist+netNodeCnt+2, INT_MAX);
		
		dist[S] = 0;
        q.push(S); 
        while(!q.empty())
        {
            int u = q.front();
            q.pop();  
			vis[u] = false;
            for(i=head[u]; i!=-1; i=edge[i].next)
			{
                int v = edge[i].to;
                if(edge[i].cap > edge[i].flow && dist[v] > dist[u]+edge[i].cost)
				{
                    dist[v] = dist[u] + edge[i].cost;
                    preV[v] = u;
                    preE[v] = i;
                    if(!vis[v])
					{
						q.push(v);
						vis[v] = true; 
                    }
                }
            }
        }
		
        if(dist[T] == INT_MAX) 
			break;
		
        int f = INT_MAX;
		int u;
        for(u=T; u!=S; u=preV[u])
		{
            int i = preE[u];
			if (edge[i].cap - edge[i].flow < f)
				f = edge[i].cap - edge[i].flow;
        }
        for(u=T; u!=S; u=preV[u])
		{
            int i = preE[u];
            edge[i].flow += f;
            edge[i^1].flow -= f;
        }
        flow += f;
        cost += dist[T] * f;
		if(cost > minCost)
			return false;
    }
	
    if (flow >= F)
    {
		if (cost < minCost)
		{ 
			minCost = cost;
			bestPath.clear();
			Result r;
			int f = 0;
			while(f < F)
			{
				int flow = INT_MAX;
				dfs(S, r, flow);
				f += flow;
			}
		}
		return true;
	}
	return  false;
}

// 搜索路径
void dfs(int u, Result &r, int &flow)
{
	if(u == T)
	{
		r.flow = flow;
		
		for (int k = T; k != S; k = preV[k])
		{
			int i = preE[k];
			edge[i].flow -= flow;
		}
		bestPath.push_back(r);
		return;
	}
	
	for(int i=head[u]; i!=-1; i=edge[i].next)
	{
		int v = edge[i].to;
		if(edge[i].flow > 0)
		{
			preV[v] = u;
			preE[v] = i;
			r.path.push_back(v);
			if(edge[i].flow < flow)
				flow = edge[i].flow;
			dfs(v, r, flow);
			r.path.pop_back();
			return;
		}
	}
}

/zkw

int min(int a, int b)
{
	return a < b ? a : b;
}

// KM重标号
bool adjust()  
{  
	int v, min = INF;  
	for (int i = 0; i < netNodeCnt+2; i++)  
	{  
		if (!vis[i])  
			continue;  
		for (int j = head[i];  j != -1; j = edge[j].next)
		{  
			v = edge[j].to;  
			if (edge[j].cap > edge[j].flow)  
				if (!vis[v] && dist[v] - dist[i] + edge[j].cost < min)  
					min = dist[v] - dist[i] + edge[j].cost;  
		}  
	}  
	if (min == INF)  
		return false;  
	for (int i = 0; i <netNodeCnt+2; i++)  
		if (vis[i])  
			vis[i] = false, dist[i] += min;  
	return true;  
}  

// 增广  
int augment(int i, int flow)  
{  
	if (i == T)  
	{  
		minCost += dist[S] * flow;  
		maxflow += flow;  
		return flow;  
	}  
	vis[i] = true;  
	
	for (int j = head[i], v; v = edge[j].to, j != -1; j = edge[j].next)  
	{
		if (edge[j].cap > edge[j].flow)
		{  
			if (vis[v] || dist[v] + edge[j].cost != dist[i]) 
				continue;  
			
			int delta = augment(v, min(flow, edge[j].cap - edge[j].flow));  
			if (delta)  
			{  
				edge[j].flow += delta;  
				edge[j ^ 1].flow -= delta;
				return delta;  
			}  
		}  
	}	
    return 0;  
}  

bool zkw(int &fit, int idx, int n)  
{  
	for(int i=0; i<idx; i++)
		edge[i].flow = 0;
    memset(dist, 0, sizeof(dist));
	minCost = maxflow = 0;  
	for (int i = 0; i < netNodeCnt; i++)
	{  
		vis[i] = false;  
	}  
	
	do  
	{  
		while (augment(S, INF))  
			memset(vis, false, sizeof(vis));  
	} while (adjust()); 
	if (maxflow < F)  
		return false;  
	fit = minCost + n * serverCost;

	// 搜路径
	bestPath.clear();
	Result r;
	int f = 0;
	while(f < F)
	{
		int flow = INT_MAX;
		dfs(S, r, flow);
		f += flow;
	}

	return true;  
} 

/初始化时用到

// 最小费用流
bool min_cost1()
{
	queue<int> q;
	int flow = 0;
	path.clear();
	
	while(1)
	{
		memset(vis, false, sizeof(vis));
		fill(dist, dist+netNodeCnt+2, INT_MAX);
		
		dist[S] = 0;
        q.push(S); 
        while(!q.empty())
        {
            int u = q.front();
            q.pop();  
			vis[u] = false;
			for(int i=head[u]; i!=-1; i=edge[i].next)
			{
                int v = edge[i].to;
                if(edge[i].cap > edge[i].flow && dist[v] > dist[u]+edge[i].cost)
				{
                    dist[v] = dist[u] + edge[i].cost;
                    preV[v] = u;
                    preE[v] = i;
                    if(!vis[v])
					{
                        q.push(v);
						vis[v] = true; 
                    }
                }
            }
		}
		
        if(dist[T] == INT_MAX) 
			break;
		
        int f = INT_MAX;
		int u;
        for(u=T; u!=S; u=preV[u])
		{
            int i = preE[u];
			if (edge[i].cap - edge[i].flow < f)
				f = edge[i].cap - edge[i].flow;
        }
		for(u=T; u!=S; u=preV[u])
		{
            int i = preE[u];
            edge[i].flow += f;
            edge[i^1].flow -= f;
		}
        flow += f;
    }
	
	bestPath.clear();
	Result r;
	int f = 0;
	while(f < F)
	{
		int flow = INT_MAX1;
		dfs(S, r, flow);
		f += flow;
	}	
	return  true;
}

// 记录结果 
void record_result1(set<int> &s)
{
	int n = bestPath.size();
	for (int p = 0; p < n; p++)
	{
		s.insert(bestPath[p].path[bestPath[p].path.size()-2]);
	}
	set<int>::iterator it;
	for(it = s.begin(); it != s.end(); it++)
	{
		vChoice.push_back(*it);
	}
}

随机算法//

int Entity::getFit1()
{
	map<int, int> m;
	int cnt = position.size();
	int fit = 0;
	
	// 保存之前的图
	set<int>::iterator it;
	for(it = position.begin(); it != position.end(); it++)
		m[*it] = head[*it];
	
	// 添加一些新边:放置服务器的网络节点连向超级汇点
	int idx = id;
	for (it = position.begin(); it != position.end(); it++)
	{
		addEdge(*it, T, INT_MAX, 0, idx);
		addEdge(T, *it, 0, 0, idx);
	}
	
	bool find = zkw(fit, idx, position.size());
	
	// 恢复之前的图
	for (it = position.begin(); it != position.end(); it++)
		head[*it] = m[*it];
	head[T] = -1;
	
	fitness = find ? fit : INT_MAX;
	return fitness;
}

int Entity::getFit()
{
	map<int, int> m;
	int cnt = position.size();
	int fit = 0;
	
	// 保存之前的图
	set<int>::iterator it;
	for(it = position.begin(); it != position.end(); it++)
		m[*it] = head[*it];
	
	// 添加一些新边:放置服务器的网络节点连向超级汇点
	int idx = id;
	for (it = position.begin(); it != position.end(); it++)
	{
		addEdge(*it, T, INT_MAX, 0, idx);
		addEdge(T, *it, 0, 0, idx);
	}
	
	bool find = min_cost(fit, idx, position.size());
	
	// 恢复之前的图
	for (it = position.begin(); it != position.end(); it++)
		head[*it] = m[*it];
	head[T] = -1;
	
	fitness = find ? fit : INT_MAX;
	return fitness;
}

// 初始化
void init()
{
	// 将所有的节点与汇点连边,费用为服务器费用
	// 挑选度最大的2个点、带宽需求最高的2个点作为服务器
	// 与汇点连边的费用为0
	// 搜索最小费用路径,将所有倒数第2个点作为服务器,加入sChoice中
	// 之后的搜索中,所有服务器都来自于sChoice
	
	set<int> s;
	for(int k=0; k<netNodeCnt; k++)
		s.insert(k);
	set<int> s1;
	s1.insert(node[0].id);  // 度最高的2个点
	s1.insert(node[1].id);
	Node node1[MAX_consumeNodeCnt];
	for(int k=0; k<consumeNodeCnt; k++)
	{
		node1[k].id = consume[k].netID;
		node1[k].degree = consume[k].demand;
	}
	sort(node1, node1+consumeNodeCnt);
	s1.insert(node1[0].id);  // 带宽需求最高的2个点
	s1.insert(node1[1].id);
	
	// 保存之前的图
	map<int, int> m;
	set<int>::iterator it;
	for(int k = 0; k < netNodeCnt; k++)
		m[k] = head[k];
	
	for(it=s1.begin(); it != s1.end(); it++)
	{
		s.erase(*it);
	}
	int idx = id;
	for(it=s.begin(); it != s.end(); it++)
	{
		addEdge(*it, T, INT_MAX1, serverCost, idx);
		addEdge(T, *it, 0, 0, idx);
	}
	for(it=s1.begin(); it != s1.end(); it++)
	{
		addEdge(*it, T, INT_MAX1, 0, idx);
		addEdge(T, *it, 0, 0, idx);
	}
	min_cost1();
	record_result1(sChoice);  
	
	// 恢复之前的图
	for (int k=0; k<netNodeCnt; k++)
		head[k] = m[k];
	head[T] = -1;
	
	start = clock();
	Best.position = sChoice;
	Best.getFit1();
}

bool accept(double delta, double temper)
{
    if(delta <= 0) 
	{
		if(Best.fitness > MostBest.fitness)
			MostBest = Best;
        return true;
	}
    //return rand() <= exp((-delta) / temper) * RAND_MAX;
	return  exp((-delta) / temper) >= 0.1;
} 

// 变异函数
void mutate()
{
	int r = rand() % 100; 
	int cnt = Best.position.size();
	
	// 替换变异
	if(r < PMUTATION1 && cnt > 0)
	{ 
		Entity M = Best;
		int a = rand() % vChoice.size();		  // 随机选取一个节点
		set<int>::iterator it;
		vector<int> v;
		for(it = M.position.begin(); it != M.position.end(); it++)
			v.push_back(*it);
		if(bad.count(vChoice[a]))                 // 如果该节点在禁忌表中
		{ 	
			if(rand() % 100 < 70)                 // 以0.3的概率重新选择一个节点
			{
				int j = rand() % v.size();
				M.position.insert(vChoice[a]);    // 加进新的
				M.position.erase(v[j]);			  // 删除旧的节点
				M.getFit1();
				if(accept(M.fitness - Best.fitness, temp))
					Best = M;
				if(temp >= thold)
					temp *= decs;
			}
		}
		else
		{
			int j = rand() % v.size();
			M.position.insert(vChoice[a]);        // 加进新的
			M.position.erase(v[j]);				  // 删除旧的节点
			M.getFit1();
			if(accept(M.fitness - Best.fitness, temp))
				Best = M;
			if(temp >= thold)
				temp *= decs;
		}	
	}

	// 删除变异
	else if (r < PMUTATION2 && cnt > 0)
	{
		Entity M = Best;
		vector<int> v;
		set<int>::iterator it;
		for(it = M.position.begin(); it != M.position.end(); it++)
			v.push_back(*it);
		int i = rand() % cnt;     // 随机选择变异个体中的某个服务器,要将其删除
		M.position.erase(v[i]);   // 除掉旧的

		M.getFit1();
		if(accept(M.fitness - Best.fitness, temp))
		{
			Best = M;
			if(temp >= thold)
				temp *= decs;
			bad.insert(v[i]);
		}
	}
		
	// 增加变异
	else
	{
		Entity M = Best;
		int a = rand() % vChoice.size();              // 另外一个服务器
		if(!M.position.count(vChoice[a]))             // 如果该节点未放置服务器
		{
			if(bad.count(vChoice[a]))                 // 如果该节点在禁忌表中
			{
				if(rand() % 100 < 70)                 // 以0.3的概率重新选择一个节点
				{
					M.position.insert(vChoice[a]);    // 加进新的
					M.getFit1();
					if(accept(M.fitness - Best.fitness, temp))
					{
						Best = M;
						if(temp >= thold)
							temp *= decs;
					}
				}
			}
			else
			{
				M.position.insert(vChoice[a]);         // 加进新的
				M.getFit1();
				if(accept(M.fitness - Best.fitness, temp))
				{
					Best = M;
					if(temp >= thold)
						temp *= decs;
				}
			}
		}
	}
}

void mainEA()
{
	init();
	double t = (double)clock() / CLOCKS_PER_SEC;
	//double t = T2.tv_sec - T1.tv_sec;
	while (t < 90)
	{
		mutate();    
		t = (double)clock() / CLOCKS_PER_SEC;
		//t = T2.tv_sec - T1.tv_sec;
		if(t > 75)
		{
			PMUTATION1 = 60;
		} 
	}

	if(Best.fitness > MostBest.fitness)
		Best = MostBest;

	finish = clock();
	double duration = (double) (finish-start)/CLOCKS_PER_SEC;   //时间以秒为单位
	cout << "时间:" << duration << endl;
	cout << "bestFit:" << Best.fitness << endl;
	cout << Best.position.size() << endl;
}

---------------------------------------主函数---------------------
cdn.cpp

#include "deploy.h"
#include "lib_io.h"
#include "lib_time.h"
#include "stdio.h"

int main(int argc, char *argv[])
{
    print_time("Begin");
    char *topo[MAX_EDGE_NUM];
    int line_num;

    char *topo_file = argv[1];

    line_num = read_file(topo, MAX_EDGE_NUM, topo_file);

    printf("line num is :%d \n", line_num);
    if (line_num == 0)
    {
        printf("Please input valid topo file.\n");
        return -1;
    }

    char *result_file = argv[2];

    deploy_server(topo, line_num, result_file);

    release_buff(topo, line_num);

    print_time("End");

	return 0;
}

---------------------------------------非核心---------------------
io.cpp

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <time.h>
#include <sys/timeb.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>

#define MAX_LINE_LEN 55000

#define INLINE  static __inline
#ifdef _DEBUG
#define PRINT   printf
#else
#define PRINT(...)
#endif


INLINE void write_file(const bool cover, const char * const buff, const char * const filename);


void print_time(const char *head)
{
//#ifdef _DEBUG
    struct timeb rawtime;
    struct tm * timeinfo;
    ftime(&rawtime);
    timeinfo = localtime(&rawtime.time);

    static int ms = rawtime.millitm;
    static unsigned long s = rawtime.time;
    int out_ms = rawtime.millitm - ms;
    unsigned long out_s = rawtime.time - s;
    ms = rawtime.millitm;
    s = rawtime.time;

    if (out_ms < 0)
    {
        out_ms += 1000;
        out_s -= 1;
    }
    printf("%s date/time is: %s \tused time is %lu s %d ms.\n", head, asctime(timeinfo), out_s, out_ms);
//#endif
}

int read_file(char ** const buff, const unsigned int spec, const char * const filename)
{
    FILE *fp = fopen(filename, "r");
    if (fp == NULL)
    {
    	PRINT("Fail to open file %s, %s.\n", filename, strerror(errno));
        return 0;
    }
    PRINT("Open file %s OK.\n", filename);

    char line[MAX_LINE_LEN + 2];
    unsigned int cnt = 0;
    while ((cnt < spec) && !feof(fp))
    {
        line[0] = 0;
        if (fgets(line, MAX_LINE_LEN + 2, fp) == NULL)  continue;
        if (line[0] == 0)   continue;
        buff[cnt] = (char *)malloc(MAX_LINE_LEN + 2);
        strncpy(buff[cnt], line, MAX_LINE_LEN + 2 - 1);
        buff[cnt][MAX_LINE_LEN + 1] = 0;
        cnt++;
    }
    fclose(fp);
    PRINT("There are %d lines in file %s.\n", cnt, filename);

    return cnt;
}

void write_result(const char * const buff,const char * const filename)
{
	// 以覆盖的方式写入
    write_file(1, buff, filename);

}

void release_buff(char ** const buff, const int valid_item_num)
{
    for (int i = 0; i < valid_item_num; i++)
        free(buff[i]);
}

INLINE void write_file(const bool cover, const char * const buff, const char * const filename)
{
    if (buff == NULL)
        return;

    const char *write_type = cover ? "w" : "a";//1:覆盖写文件,0:追加写文件

    FILE *fp = fopen(filename, write_type);
    if (fp == NULL)
    {
        PRINT("Fail to open file %s, %s.\n", filename, strerror(errno));
        return;
    }
    PRINT("Open file %s OK.\n", filename);
    fputs(buff, fp);
    fputs("\n", fp);
    fclose(fp);
}

lib_io.h

#ifndef __LIB_IO_H__
#define __LIB_IO_H__

#define MAX_EDGE_NUM    (2000 * 20)

//读取文件并按行输出到buff。
//buff为一个指针数组,每一个元素是一个字符指针,对应文件中一行的内容。
//spec为允许解析的最大行数。
extern int read_file(char ** const buff, const unsigned int spec, const char * const filename);

//将result缓冲区中的内容写入文件,写入方式为覆盖写入
extern void write_result(const char * const buff,const char * const filename);

//释放读文件的缓冲区
extern void release_buff(char ** const buff, const int valid_item_num);

#endif

lib_time.h

#ifndef __LIB_TIME_H__
#define __LIB_TIME_H__

//打印时间。入参为打印信息头
void print_time(const char * const head);

#endif

高级用例 case0.txt,800节点,3022条边,360个消费者节点
结果:104863

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值